Summary: Information on using the Dss runtime to build service applications

CCR Patterns

For common CCR messaging patterns in DSS see this page: CommonCCRMessagingPatternsInDSS

Dss Contracts

Using Alternate Contracts and Alternate Ports: AlternateContracts
Creating Reusable Generic Contracts: GenericContracts

Hosting Dss Services

You don't have to use @DssHost.exe@ to execute your services. You can use the @DssEnvironment.dll@ assembly and the @DssEnvironment@ static class to initialize the DSS runtime within an application of your choice or .NET NT Service.

Example of a C# EXE hosting DSS:
		  class Program
		  {
		      static void Main(string[] args)
		      {
		          // initialize Dss using some manifests
		          [DssEnvironment.Initialize(808,] 809,
		              @"C:\MRI\main\Builds\x86dbg\Layout Files\samples\config\SimulationTutorial1.manifest.xml",
		              @"C:\MRI\main\Builds\x86dbg\Layout Files\samples\config\SimulationTutorial2.manifest.xml"
		              );
	

		          // bind outbound port to directory service for node we just started
		          [ds.DirectoryPort] directoryService = 
		              [DssEnvironment.ServiceForwarder<ds.DirectoryPort>]
		              (new Uri("http://localhost:808/directory/"));
		          ds.Get get = new [ds.Get(dssp.GetRequestType.Instance);]
		          // issue request
		          directoryService.Post(get);
	

		          // wait for response
		          [Arbiter.Activate(DssEnvironment.TaskQueue,]
		              Arbiter.Choice(
		              [get.ResponsePort,]
		              [delegate(ds.GetResponse] rsp) { Console.WriteLine("Got directory response"); },
		              delegate(W3C.Soap.Fault f) { })
		          );
	

		          System.Threading.Thread.Sleep(5000);
	

		          [DssEnvironment.Shutdown();]
		      }
		  }
	

Finding Service Instances

A DSS node always contains a local service directory where services advertise themselves on startup. You can use the directory to subscribe for service creation/shutdown or to find a service based on contract. Continuing the example of a self hosted EXE above, take a look at this example of finding a service and sending a message to it. This code can also work within a service, of course, if you replace the use of the @DssEnvironment@ static methods and just the @DsspBaseService.ServiceForwarder@ and @DsspServiceBase.DirectoryPort@ fields.

Note You can issue @Query@ or @Subscribe@ operations to any directory service from the local or remote node.

Example:
		        static [IEnumerator<ITask>] [FindAndInsertToConsole(ds.DirectoryPort] directoryPort)
		        {
		            // subscribe for a service. We subscribe for the console output service, as an example
		            [ds.DirectoryPort] notificationTarget = new [ds.DirectoryPort();]
		            [ds.SubscribeRequest] subscribe = new [ds.SubscribeRequest();]
		            // we only want one notification, first service that matches criteria
		            [subscribe.NotificationCount] = 1;
		            [subscribe.QueryRecordList.Add(new] [dssp.ServiceInfoType(console.Contract.Identifier));]
	

		            yield return Arbiter.Choice(
		                directoryPort.Subscribe(subscribe, notificationTarget),
		                [delegate(dssp.SubscribeResponseType] rsp) { },
		                delegate(Fault f)
		                {
		                    notificationTarget = null;
		                });
	

		            if (notificationTarget == null)
		            {
		                Console.WriteLine("Subscription failed to directory");
		                yield break;
		            }
	

		            [console.ConsoleOutputPort] consolePort = null;
		            // listen for a single notification for a service instance
		            yield return Arbiter.Receive<ds.Insert>(false, notificationTarget,
		                delegate(ds.Insert insNotify)
		                {
		                    Console.WriteLine("Service uri:" + insNotify.Body.Record.Service);
		                    // get a port we can use to talk to the service
		                    consolePort =
		                        [DssEnvironment.ServiceForwarder<console.ConsoleOutputPort>]
		                        (new Uri(insNotify.Body.Record.Service));
		                });
	

		            // create insert message
		            [console.InsertRequest] insBody = new [console.InsertRequest();]
		            insBody.Subject = "test";
	

		            // check operation result and send all in one statement
		            yield return Arbiter.Choice(
		                consolePort.Insert(insBody), // Sends Insert
		                [delegate(dssp.DefaultInsertResponseType] success) { },
		                delegate(Fault f) { Console.WriteLine("Insert failed"); }
		            );
	

		            // clean shutdown of dss node
		            [DssEnvironment.Shutdown();]
	

		        }
	

Throttling notifications

Many times you want to just keep the most recent notification from a service, and have the system throw away anything beyond that. It also avoids the real issue of falling behind and your ports growing arbitrarily large.
Let assume you have the usual code snippet where you subscribe to a sensor, and supply a notification port to receive the update messages. I cut and pasted a simple example from robotics Tutorial 2 (as is):

		        void [SubscribeToBumpers()]
		        {
		            // Create bumper notification port
		            [bumper.ContactSensorArrayOperations] [bumperNotificationPort] = new [bumper.ContactSensorArrayOperations();]
	

		            // Subscribe to the bumper service, send notifications to [bumperNotificationPort]
		            _bumperPort.Subscribe(bumperNotificationPort);
	

		            // Start listening for Bumper Replace notifications 
		            Activate(
		                Arbiter.Receive<bumper.Update>
		                    (true, [bumperNotificationPort,] [BumperHandler));]
		        }
	

I would modify it as follows (see boldface text below):

		        void [SubscribeToBumpers()]
		        {
		            // Create bumper notification port
		            [bumper.ContactSensorArrayOperations] [bumperNotificationPort] = new [bumper.ContactSensorArrayOperations();]
	

		            // Subscribe to the bumper service, send notifications to [bumperNotificationPort]
		            _bumperPort.Subscribe(bumperNotificationPort);
	

		            // maximum depth set to 1, will discard anything but latest
		            [DispatcherQueue] [notifyTaskQueue] = new DispatcherQueue("bumperNotifyQueue",
		                [TaskQueue.Dispatcher,] // use same dispatcher as service
		                [TaskExecutionPolicy.ConstrainQueueDepthDiscardTasks,] 1);
	

		            // Start listening for Bumper Replace notifications 
		            Arbiter.Activate(
		                [notifyTaskQueue,]
		                Arbiter.Receive<bumper.Update>
		                    (true, [bumperNotificationPort,] [BumperHandler));]
		        }
	

Basically a created a private queue, with a custom policy. It will keep the most recent item, not the oldest, which is what you need
Microsoft Communities