Sticky New features of DSS Service model, in MSRDS2008

  • Friday, April 18, 2008 5:08 PM
     
     

    Our whats new page has details, but i would like to re-iterate here:

     

    1) Periodic code no longer requires you to use TimeoutPort and re-activate a handler. Just add an argument, with the Interval in seconds (its a double, so say 0.010 for 10ms) in your ServiceHandlerAttribute!

     

    From updated Service Tutorial 4 (Tutorial 3 has the old way, look at the code savings)

    Code Snippet

            [ServiceHandler(ServiceHandlerBehavior.Exclusive, Interval=1)]
            public IEnumerator IncrementTickHandler(IncrementTick incrementTick)
            {

     

     

    2) A new attribute [ServiceState], when placed on the field that holds the state instance for your service, allows us to take care of Dssp GET and HttpGET for you!. No need for writing HttpGet an GET handlers anymore, even if you have XSLTs!. If you have a transform, add it to the attribute. Your service basically no longe rneed ot handle HttpGet, Get, Lookup, Drop if its in the most common case. See updated service tutorial 6:

     

            [ServiceState(StateTransform = "RoboticsServiceTutorial6.ServiceTutorial6.xslt")]
            private ServiceTutorial6State _state = new ServiceTutorial6State();

    3) Instead of the very long Partner attribute for the common usage of a SubscriptionManager Partner service, now you can just type [SubscriptionManagerPartner]. See update service tutorial 4

     

            [SubscriptionManagerPartner]
            private submgr.SubscriptionManagerPort _submgrPort = new submgr.SubscriptionManagerPort();

     

    compare this to the old way:

     

    Code Snippet

    [Partner("SubMgr", Contract = submgr.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.CreateAlways)]

     

     

    4) We now have LINQ persistent subscriptions, that do arbitrary filtering on the site of the service publisher. See user guide section:

     

    A powerful feature of the Subscription Manager is allowing the user to specify LINQ queries, as simple methods that operate on service state and service messages. The LINQ filters are encapsulated in an implementation of the DataContractFilter class, so they can be parameterized, stateful and verified by the compiler.

    In addition, DSS now supports sending the LINQ Filters to the subscription manager, even if it is on a remote node. This means the computation (filtering) happens where the data is produced, and because its completely defined by the user, not the author of the service that publishes the data, it can do arbitrary filtering with no modifications required by the service author.

    To summarize LINQ as subscription filters provides

    • Custom compiler verified filtering - Arbitrary filtering specified by the consumer of a service, with no prior knowledge required by the author of the service publishing data. Services can now just produce Replace notifications and not have custom Update notifications for every useful sub-part of their state
    • Simplified publisher model- Computation moves automatically to the data source (any DSS service) with the potential to drastically reduce notifications and bandwidth use on the wire. Developer no longer need to issue Get or Query operations to a service if they wish to perform arbitrary filtering
    • Dynamic code transfer - DSS infrastructure will automatically transfer the filter implementation assembly to the remote node the publisher service executes, enabling true distributed, concurrent queries
    • Isolated, restricted code execution - Filter expressions are a restricted set code that cant issue arbitrary requests to the system and only has access to variables defined within the filter class. The state or operations they operate on are cloned versions of the service state
    • Stateful, parametric filtering - A filter class can use private instance members to keep track of previous notifications and results and apply them in the same LINQ query that processes the current service notification. This allows advanced functionality, such as statistics based filtering or thresholding to occur inside the filter, side by side with the publisher service

    Defining Data Contract LINQ Filters

    An example of a filter on the console output service is given below. The particular example applies a filter on the entire state of the console service. For each item in the queue of logged items, we find the messages that have a specific level (supplied when the filter class was initialized) and the Category equal LogGroups.Activation ( a pre defined Xml qualified name)

     

    public class ConsoleActivationFilterParametricOnLevel : DataContractFilter
    {
        public string Level;
    
        public ConsoleActivationFilterParametricOnLevel()
        {
            Expression<func><consoleproxy.messagetype>>> exp =
                (consoleproxy.QueueType state) =>
                from item in state.MessageList
                where (item.Category == LogGroups.Activation && item.Level.ToString() == Level)
                select item;
            base.QueryHandler = exp.Compile();
        }
    }
    

     

    To create a subscription with the above filter, the same steps are taken as with other types of filters. A new field on the Subscribe operation allows for one or more LINQ filters to be specified

        DataContractFilter filterOnProxy =
            new ConsoleActivationFilterParametricOnLevel() { Level = console.LevelType.InfoString};
        console.ConsoleOutputPort notify = new console.ConsoleOutputPort();
        console.Subscribe subscribe = new console.Subscribe(new console.SubscribeRequest());
        subscribe.NotificationPort = notifyPort;                
        // add LINQ filter
        subscribe.AddHeader(filterOnProxy);
        // issue subscribe to console service
        consolePort.Post(subscribe);
    

    A few key points to notice on the above sample

    • The class implementing the filter (ConsoleActivationFilterParametricOnLevel) is a user defined class that must derive from DataContractFilter, defined in DssBase.dll. The class can be part of a standalone C# assembly
    • The filter operates on the proxy types of the publisher service (Console Output service in this case) but can also use the service implementation types directly
    • The filter can operate on the entire state, which means its invoked only when Replace operations occur, or on individual Update notifications

    Consuming filtered notifications

    When notifications are issued, the LINQ filter results must be retrieved from the Headers field collection in the notification operation. The result of a LINQ query over a service state or service notification can be arbitrary types of data that might not be directly serializable. The infrastructure gets around this by wrapping the results in the DataContractFilterResults class and places an instance in the headers of every notification.

        Activate(
            Arbiter.Receive(true, notifyPort,EmptyHandler),
            Arbiter.Receive(false, notifyPort, replace =>
            {
                var filteredResults = replace.GetHeader>();
                foreach (console.MessageType filteredItem in filteredResults.QueryResults)
                {
                   // process each item that passed the filter
                }
            });
    

    Custom filters on individual notifications

    The previous examples focused on applying a LINQ expression on collection types. You can also filter individual notifications where the body is a single instance instead of a collection.

        public class ConsoleActivationFilterOnMessageType : DataContractFilter
        {
            public ConsoleActivationFilterOnMessageType()
            {
                Expression>> exp =
                    (consoleproxy.MessageType insertNotification) =>
                    from item in new consoleproxy.MessageType[] {insertNotification}
                    where (item.Level.ToString() == consoleproxy.LevelType.InfoString)
                    select item;
                base.QueryHandler = exp.Compile();
            }
        }
    

    Notice that in order to apply the LINQ from keyword on an individual message, we created an array dynamically with a single element. More advanced functionality, like grouping can also be achieved using filters. The reader should review the LINQ documentation available on MSDN and Visual Studio Help to better understand the potential of DSS subscription filters with LINQ.

All Replies

  • Friday, April 18, 2008 10:31 PM
     
     

    Nice, thanks, some questions I still have:

     

    for case 1, will it support dynamic intervals in the future? e.g. an interval from a state file? 

     

    for case 2 (ServiceState) can we access the StateTransform field directly, so we can remove the _transform completely? (e.g. in a HttpPost handler?)

     

    Also, is there still the need to call the MountResources?

     

    Thanks, Erik

     

  • Monday, April 28, 2008 9:18 PM
     
     
    1) dynamic intervals are not planned to be supported. To do this, you will need to write code, as before

    2) Yes, it in a new field in the DsspServiceBase class, ServiceStateTransform (i might get the field name wrong, but its there). So you can use that URI directly as well (for your query responses for example, HttpPost, etc)

    3) There is no need to call MountResources if you use this [ServiceState] attribute or the InitialStateAttribute

     

  • Thursday, February 12, 2009 9:07 PM
     
     
    Where can I find the 
    SubscriptionManagerPartner attribute class?



  • Sunday, May 03, 2009 8:06 PM
    Owner
     
      Has Code
    This is an attribute that you can apply to a subscription manager port. It is not a class that you instantiate. Why do you need to know more about it?

    Trevor