Deploying StreamInsight Entities to a StreamInsight Server
StreamInsight entities operate within a StreamInsight application that runs in a StreamInsight server. A StreamInsight program can embed and use a StreamInsight server in-process, or it can connect to a remote server which can be shared by multiple clients. If you configured a StreamInsight Host Windows service when you installed StreamInsight, then you can connect to that service which acts as a remote server. In addition, a StreamInsight program can expose an end point for an embedded server to make it accessible to other client programs. For more information on configuring a StreamInsight server, see Publishing and Connecting to the StreamInsight Server.
Whether the server is embedded or remote, a client defines an entity (source, sink, subject, or binding) locally and then has the option to deploy it in the server. After the entities are deployed, a client connected to the server can get a handle for a deployed entity and then bind and run the entities in the server.
For example, suppose we have three StreamInsight clients and a remote server. Note that the remote server can be a StreamInsight Host Windows service, as in Figure 1, or it can be an embedded server within a StreamInsight program that has exposed an end point for the server, as in Figure 2. A client connecting to the server end point does not need to be aware of the server deployment model used. For more information, see StreamInsight Server Deployment Models.
Define an entity
Client 1 defines a data source that later will be deployed to the server. In this example the source is a simple sequence of numbers:
IQbservable<int> mySource1 = app.DefineObservable(() => Observable.Range(0, 10));
DefineEnumerable, DefineObservable, and DefineStreamable are methods used to define expressions intended to be evaluated by the server; the data source is defined locally and exists only in the client at this point.
Deploy an entity to the server
Client 1 then deploys the composed entity to the server, as shown in Figure 4. The entity must be named when it is deployed, which enables it to be discovered and managed by other clients.
Deploying the source to the server places a copy of the definition of the source in the server where other clients can use it.
Get a handle to a server entity
As shown in Figure 5, Client 2 now constructs a handle to the deployed source by using a get method:
var mySource2 = app.GetObservable<int>("serverSource");
The IQbservable<int> instance returned by GetObservable is a handle for the source in the server, although no actual connection to the server is established at the time the handle is created. The connection is attempted when data is ready to be generated from the source, for example when you run a binding - the process will fail if the entity no longer exists at the time you run the binding.
Bind and run entities
A client can define a binding that may be deployed and run in the server. For example, in Figure 6, Client 3 defines and deploys a sink to the server and uses a get method to create a handle to the existing source in the server:
var mySink3 = app.DefineObserver(() => Observer.Create<int>(x => Console.WriteLine(x))); mySink3.Deploy("serverSink"); var mySource3 = app.GetObservable<int>("serverSource");
Client 3 now can define a binding of the source and sink and create a named running process that executes the binding in the server, as shown in Figure 7. The binding itself is not stored on the server, it just identifies the connection between the source and sink entities on the server. Client 3 creates a binding using the handle for the source definition in the server and the local sink definition:
var binding = mySource3.Bind(mySink3); binding.Run("serverProcess");
Alternatively Client 3 could create the binding and run it in one step.
The source and sink definitions on the server are used to create the process. Note that when using a remote server as in this example, the process runs within the context of the remote server - any data or procedures needed by a bound source, query, sink, or subject must be available to the server at the time the process runs.
Manage a server entity
Entities can be deleted on the server, as shown in Figure 8, by any client that knows the name of the entity. In this example, Client 3 has instructed the server to delete serverSource by simply writing the following:
Note that Client 2 still has a handle for the entity in the server. If Client 2 attempts to use the handle to bind the entity and run a process after the entity has been deleted, the process will fail. Clients need to account for this possibility when working with entity handles.
Create a subject
A client also can create a subject on the server. For example, a client can create a subject as follows:
var mySubject = app.CreateSubject<long,long>("serverSubject", () => new Subject<long>());
The subject is created in the server with the name serverSubject, and the local variable mySubject is a handle to the object. Note that when a source or sink is deployed to the server an actual object is not created, only the definition of the source or sink is stored in the server. However, creating a subject creates an object on the server.
A subject is a unique entity that can be bound to both sources and sinks, consuming data from the sources and passing data on to the sinks.
For example, Client 3 can bind the subject to the sink defined earlier (assume that the sink has not been deleted as in the previous example) and run a process, as shown in Figure 9:
Because the subject is not bound to a source there is not yet any data flowing to the sink.
Then suppose that Client 3 defines a query q1 over the source mySource3:
var q1 = from x in mySource3 where x % 2 == 0 select x;
And binds the subject to the query, as shown in Figure 10:
At this point data starts flowing from the source through the query to the subject, and then from the subject to the sink.
An additional binding can be added to the subject, as shown in Figure 11:
var q2 = from y in mySource3 select y * 1000; q2.Bind(mySubject).Run("serverSubjectProcess3");
In this example the subject is taking data from two different queries over the same source and sending the combined data to the sink. Additional, multiple sources and sinks can be bound and run using the same subject.