0
votes

I am having a great experience with ServiceStack & Redis, but I'm confused by ThreadPool and Pub/Sub within a thread, and an apparent limitation for accessing Redis within a message callback. The actual error I get states that I can only call "Subscribe" or "Publish" within the "current context". This happens when I try to do another Redis action from the message callback.

I have a process that must run continuously. In my case I can't just service a request one time, but must keep a thread alive all the time doing calculations (and controlling these threads from a REST API route is ideal). Data must come in to the process on a regular basis, and data must be published. The process must also store and retrieve data from Redis. I am using routes and services to take data in and store it in Redis, so this must take place async from the "calculation" process. I thought pub/sub would be the answer to glue the pieces together, but so far that does not seem possible.

Here is how my code is currently structured (the code with the above error). This is the callback for the route that starts the long term "calculation" thread:

    public object Get(SystemCmd request)
    {
        object ctx = new object();
        TradingSystemCmd SystemCmd = new TradingSystemCmd(request, ctx);

        ThreadPool.QueueUserWorkItem(x =>
        {
            SystemCmd.signalEngine();
        });
        return (retVal);  // retVal defined elsewhere
    }

Here is the SystemCmd.signalEngine():

       public void signalEngine(){

        using (var subscription = Redis.CreateSubscription())
        {            
            subscription.OnSubscribe = channel =>
            {
            };

            subscription.OnUnSubscribe = channel =>
            {
            };

            subscription.OnMessage = (channel, msg) =>
            {

                    TC_CalcBar(channel, redisTrade);

            };


            subscription.SubscribeToChannels(dmx_key); //blocking
        }
    }

The "TC_CalcBar" call does processing on data as it becomes available. Within this call is a call to Redis for a regular database accesses (and the error). What I could do would be to remove the Subscription and use another method to block on data being available in Redis. But the current approach seemed quite nice until it failed to work. :-)

I also don't know if the ThreadPool has anything to do with the error, or not.

1
I have confirmed by testing that a Sub callback is limited to Pub / Sub operations, at least on the same Redis connection. I am a bit surprised that this isn't a bigger topic as I've never seen any posts on it. It would be good to know if you can make a different Redis connection and access the DB that way?tradetree
I know this is an old thread, but yes, what you describe in your comment is the correct approach; leave the one RedisClient dedicated to the subscription, and use another to read/write from Redis upon receiving your signal.Dusty

1 Answers

2
votes

As per Redis documentation:

Once the client enters the subscribed state it is not supposed to issue any other commands, except for additional SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE and PUNSUBSCRIBE commands.

Source : http://redis.io/commands/subscribe