locked
Service Not Dropping Properly? RRS feed

  • Question

  • Now that I fixed my auto-subscribe issue (Thanks Dave Lee), I've noticed some very odd and unexpected.

     

    To lay the background info:

     

    I have ServiceA, and ServiceB. ServiceA starts up, and attempts to subscribe to serviceB at a regular interval. If no ServiceB is found (by querying the Directory Service), it simply continues to check. It gives a debug notification when a subscription is successful. ServiceB starts up next, and sends out a message containing a string (and counter for message identification) at a regular interval, using a Timeoutport. ServiceA has a receiver setup to handle this message. Both services are started and dropped using the web interface Control Panel.

     

    Looking at the debug output below, you can follow the general order of things.

     

    Now, what I wanted to test was ServiceA's ability to handle ServiceB dropping and then restarting (which it should be able to handle just fine). Before I got there, I noticed something strange. When I hit the "Drop" button on the Control Panel for ServiceB, it apperently was dropped from the Directory Service, because ServiceA correctly identifies that ServiceB has dropped (step 18). However, you'll notice that ServiceA continues to receive messages from ServiceB, after it has been dropped! What's stranger, is that in the same block of code, ServiceB sends the message to it's Subscription Manager (built in), and also posts a debug message, yet the debug message no longer appears. One should not happen without the other happening.

     

    Also, I'm using a port that is a part of mainPort. I was under the impression that a drop message would automatically remove any receivers listening on the mainPort. If that's the case, the Timeoutport message should never get handled and the messages should not be sent. Yet, somehow, ServiceA continues to receive them.

     

    Any ideas?

     

     

    3 16:26:15 ** Service uri:
    4 16:26:15 *** Service A Started
    5 16:26:24 ** Service uri:
    6 16:26:24 *** Service B Started
    7 16:26:24 ** Service B Sent: Here is the Message, counter: 1
    8 16:26:26 ** Service A subscribed to Service B
    9 16:26:29 ** Service B Sent: Here is the Message, counter: 2
    10 16:26:29 ** Service A Received: Here is the Message, counter: 2
    11 16:26:34 ** Service B Sent: Here is the Message, counter: 3
    12 16:26:34 ** Service A Received: Here is the Message, counter: 3
    13 16:26:39 ** Service B Sent: Here is the Message, counter: 4
    14 16:26:39 ** Service A Received: Here is the Message, counter: 4
    15 16:26:44 ** Service B Sent: Here is the Message, counter: 5
    16 16:26:44 ** Service A Received: Here is the Message, counter: 5
    17 16:26:47 * ### Transport:http://dgfslqc1:40000/:Node shutdown, aborting http listen
    18 *** Service A has lost connection to Service B. Will Attempt to re-subscribe
    19 16:26:49 ** Service A Received: Here is the Message, counter: 6
    20 16:26:54 ** Service A Received: Here is the Message, counter: 7
    21 16:26:59 ** Service A Received: Here is the Message, counter: 8
    22 16:27:04 ** Service A Received: Here is the Message, counter: 9
    23 16:27:09 ** Service A Received: Here is the Message, counter: 10
    24 16:27:14 ** Service A Received: Here is the Message, counter: 11
    25 16:27:19 ** Service A Received: Here is the Message, counter: 12
    26 16:27:24 ** Service A Received: Here is the Message, counter: 13

     

    Thanks,

    Don

    Monday, November 19, 2007 9:47 PM

Answers

  •  

    Note that if you call base.Start() in your Start() method, the infra will handle Drop and Lookup for you, *unless* you have the ServiceBehaviorHandler attribute on your drop handler.

     

    Basically there is no need to add your drop handler in an interleave, just add the attribute on your handler, call base.Start() and we will then use your handler.

     

    Our samples show the best pattern for Drop (see for example the webcam service). Below is all you need, also shows how to drop your subscription manager partner

     

    Code Block

            [ServiceHandler(ServiceHandlerBehavior.Teardown)]
            public void DropHandler(dssp.DsspDefaultDrop drop)
            {
                _subMgrPort.Post(new dssp.DsspDefaultDrop(dssp.DropRequestType.Instance));
                base.DefaultDropHandler(drop);
            }

     

     

    Also, in your start routine do this:

     

    base.Start();

    MainPortInterleave.CombineWith(

    Arbiter.Interleave(

    new TeardownReceiverGroup(),

    new ExclusiveReceiverGroup(),

    new ConcurrentReceiverGroup(

        Arbiter.ReceiveWithIterator<TESTB.< FONT>TimerPort>(true, _mainPort, TimerHandler)

    )

    ));

     

    this is the pattern for adding your own custom interleave to the existing one, formed when you call base.Start()

    Wednesday, November 21, 2007 12:13 AM

All replies

  • Hi Don, if you have a little timer operating seperately than your main interleave, then evne if your Service Processes a drop, your other CCR tasks might still continue to operate.

     

    I usually do the following when it comes to timers:

     

    1) add a persisted receiver on a port, lets say a timer port, and then add make that receiver part of your exclusive group

    2) from within your timer handler, schedule a timeout that posts the next msg on your timer port. YOu will need to post the initial time out msg on your timer port, in your Start method to kick things off

    3) when drop happens, your timer handler will be removed and no logner process or scheduler time events

     

    Now one thing we DONT do, is drop your subscription manager. You will need to Drop it in your DropHandler (for service B). This all explains why you still see messages in service A. YOur timer is still running in service B, and the ServiceB subMgr is still active...

     

    When no more handlers active then your service will get garbage collected, etc

     

    g

     

    Tuesday, November 20, 2007 5:11 AM
  • Hi George,

     

    Thanks for the response.

     

    What you described is what I'm doing, I think. Here is the code:

     

    Code Block

    Activate(Arbiter.Interleave(

    new TeardownReceiverGroup

    (

    ),

    new ExclusiveReceiverGroup

    (

    ),

    new ConcurrentReceiverGroup

    (

    Arbiter.ReceiveWithIterator<TESTB.<TESTB.< FONT>TimerPort>(true, _mainPort, TimerHandler)

    )

    ));

     

    LogError("Service B Started");

    _mainPort.Post(new testB.TimerPort());

     

     

    and then...

     

    Code Block

    public IEnumerator<ITask> TimerHandler(testB.TimerPort timerPort)

    {

    counter++;

    testB.MessageTypeB1Request newMessageB1 = new testB.MessageTypeB1Request();

    newMessageB1.TypeB1String = "Here is the Message, counter: " + counter;

    LogInfo("Service B Sent: " + newMessageB1.TypeB1String);

    SendNotification<testB.<TESTB.< FONT>MessageTypeB1>(_subMgr, newMessageB1, new string[] { "B1" });

     

    Activate(

    Arbiter.Receive(false, TimeoutPort(5000),

    delegate(DateTime time)

    {

    _mainPort.Post(new testB.TimerPort());

    }

    )

    );

     

    yield break;

    }

     

     

    You said that when the drop happens, the TimerHandler should be removed, but this is not the case, or at least, not what it seems.

     

    Also, I don't know exactly how to drop my subscription manager. I think I'm using a unique subscription manager for each service, although subscription managers don't seem to show up in the service directory for me anymore. Is there a reason for this?

     

    In my drophandler, what would I need to add?

     

    Code Block

    public void DropHandler(DsspDefaultDrop drop)

    {

    // drop subscription manager here

     

    LogError("Service B Shutdown");

    }

     

     

     

    Thanks,

    Don

     

    Tuesday, November 20, 2007 6:14 AM
  • Furthermore, I cannot seem to get the DropHandler to even fire. I have:

     

    Code Block

    Activate(Arbiter.Interleave(

    new TeardownReceiverGroup

    (

    Arbiter.Receive<DsspDefaultDrop>(false, _mainPort, DropHandler)

    ),

    new ExclusiveReceiverGroup

    (

    ),

    new ConcurrentReceiverGroup

    (

    Arbiter.ReceiveWithIterator<TESTB.< FONT>TimerPort>(true, _mainPort, TimerHandler)

    )

    ));

     

     

    with:

     

    Code Block

    public void DropHandler(DsspDefaultDrop drop)

    {

     

    LogError("Service B Shutdown");

    }

     

     

     

    I never see the "Service B Shutdown" message when I drop the service from Control Panel. What am I doing wrong here?

     

    Thanks,

    Don

    Tuesday, November 20, 2007 8:11 PM
  •  

    Note that if you call base.Start() in your Start() method, the infra will handle Drop and Lookup for you, *unless* you have the ServiceBehaviorHandler attribute on your drop handler.

     

    Basically there is no need to add your drop handler in an interleave, just add the attribute on your handler, call base.Start() and we will then use your handler.

     

    Our samples show the best pattern for Drop (see for example the webcam service). Below is all you need, also shows how to drop your subscription manager partner

     

    Code Block

            [ServiceHandler(ServiceHandlerBehavior.Teardown)]
            public void DropHandler(dssp.DsspDefaultDrop drop)
            {
                _subMgrPort.Post(new dssp.DsspDefaultDrop(dssp.DropRequestType.Instance));
                base.DefaultDropHandler(drop);
            }

     

     

    Also, in your start routine do this:

     

    base.Start();

    MainPortInterleave.CombineWith(

    Arbiter.Interleave(

    new TeardownReceiverGroup(),

    new ExclusiveReceiverGroup(),

    new ConcurrentReceiverGroup(

        Arbiter.ReceiveWithIterator<TESTB.< FONT>TimerPort>(true, _mainPort, TimerHandler)

    )

    ));

     

    this is the pattern for adding your own custom interleave to the existing one, formed when you call base.Start()

    Wednesday, November 21, 2007 12:13 AM
  • Thanks George, that did it.

     

    This of course led to other problems, but those will be the subject of another thread.

     

    -Don

    Wednesday, November 21, 2007 3:59 AM
  • One thing George mentioned that is worth making explicit: always call base.DefaultDropHandler(drop) inside your drop handler.  Otherwise, whoever sends the drop will be blocked waiting for a response.




    Thursday, November 22, 2007 5:19 PM