Session Service Basics#
Tip
Explore the gRPC API using gRPC UI.
This provides an intuitive web interface to issue API calls and see the responses.
Opening a Channel#
The network connection to a server is called a channel in most gRPC bindings.
This should be reused across service calls where possible, for efficiency.
The session store service is provided by the Toolkit Session Service (default port 2652) and RTA Server (default port 8082).
using var sessionChannel = GrpcChannel.ForAddress("http://localhost:2652");
var sessionClient = new SessionStore.SessionStoreClient(sessionChannel);
Creating/Updating a Session#
In this example, CreateIfNotExists
defines the initial properties to set if the session does not already exist, along with Updates
to be applied in the same transaction.
If the session does exist, only the Updates
are applied.
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "001",
CreateIfNotExists = new()
{
Identifier = "Demo Session",
Timestamp = "2021-03-14T12:15:30Z",
State = (int)SessionState.Closed
}
});
{
"identity": "001",
"state": "closed",
"timestamp": "2021-03-14T12:15:30Z",
"identifier": "Demo session"
}
Each SessionUpdate
can only do one operation:
Incorrect
In this example, only SetQuality
is executed:
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Updates =
{
new SessionUpdate
{
SetType = "type66",
SetQuality = 0.25
}
}
});
Correct
In this example, SetType
and SetQuality
are executed in a single transaction:
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Updates =
{
new SessionUpdate
{
SetType = "type66"
},
new SessionUpdate
{
SetQuality = 0.25
}
}
});
Updates to collections offer a consistent pattern of operations:
Set...
— overwrites the collectionUpdate...
— adds and updates itemsDelete...
— deletes the specified items
For example, when defining relationships, these two samples are equivalent:
Starting with "ref:aaa"
, "ref:bbb"
, "ref:ccc"
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Updates =
{
new SessionUpdate
{
SetRefAnchors = new()
{
RefUris =
{
"ref:aaa",
"ref:bbb",
"ref:ccc"
}
}
}
}
});
Merge update using Update
and Delete
:
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Updates =
{
new SessionUpdate
{
UpdateRefAnchors = new()
{
RefUris =
{
"ref:ccc",
"ref:ddd"
}
}
},
new SessionUpdate
{
DeleteRefAnchors = new()
{
RefUris =
{
"ref:aaa"
}
}
}
}
});
Result:
"ref:bbb"
"ref:ccc"
"ref:ddd"
Note
Notice that the overlap with "ref:ccc"
is allowed. This is similar to JSON patching.
Starting with "ref:aaa"
, "ref:bbb"
, "ref:ccc"
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Updates =
{
new SessionUpdate
{
SetRefAnchors = new()
{
RefUris =
{
"ref:aaa",
"ref:bbb",
"ref:ccc"
}
}
}
}
});
Overwriting with Set
:
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Updates =
{
new SessionUpdate
{
SetRefAnchors = new()
{
RefUris =
{
"ref:bbb",
"ref:ccc",
"ref:ddd"
}
}
}
}
});
Result:
"ref:bbb"
"ref:ccc"
"ref:ddd"
Note
Notice that "ref:aaa"
is removed from the list.
Fetching and Listing Sessions#
The Session Service API provides the same query capabilities as the REST API, but with an extended data model covering Relationships, Folders and Data Bindings.
These elements are opt-in through the SessionElements
mask:
var session = await sessionClient.GetSessionAsync(new GetSessionRequest
{
Identity = "example",
Elements = new()
{
Json = true,
Refs = true,
Folders = true,
DataBindings = true
}
});
Tip
The MAT.OCS.RTA.Toolkit.API.GrpcClients NuGet package provides a convenience method to retrieve and parse the JSON Session Model:
var sessionModel = await sessionClient.GetSessionJsonAsync("example");
Listing sessions works the same way, using the same query dialect as the REST API:
var list = await sessionClient.ListSessionsAsync(new ListSessionsRequest
{
Query = "{\"identifier\": \"Example\"}",
SessionElements = new()
{
Json = true,
DataBindings = true
}
});
Sequenced Updates#
The CreateOrUpdateSessionRequest
has an optional sequence
field, which can help avoid re-applying stale session updates when working with a checkpoint-based system like Apache Kafka.
If populated, the service will apply the update only if the specified sequence number is greater than previous sequence numbers. As the sequence monotonically increases — for example, using a Kafka message offset — it is safe to replay a sequence of updates without causing the session metadata to roll back.
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Sequence = 100,
Updates =
{
new SessionUpdate
{
SetType = "aaa"
}
}
});
await sessionClient.CreateOrUpdateSessionAsync(new CreateOrUpdateSessionRequest
{
Identity = "example",
Sequence = 120,
Updates =
{
new SessionUpdate
{
SetType = "bbb"
}
}
});
Deleting Sessions#
Multiple sessions can be deleted in one operation, and deletion completes without error even if a session does not exist:
await sessionClient.DeleteSessionsAsync(new DeleteSessionsRequest
{
Identities =
{
"example",
"xxx-does-not-exist-xxx"
}
});