-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make the GrainClient class non-static #467
Comments
This is a great initiative. So the 1st one to look is So I suggest we focus on this place first. Once we solved this place, we can identify all other similar places and only after we changes those we can look at making a breaking API change to application code, which will be a result of making |
GrainClient
class non-static
GrainClient
class non-static
Early thinking on this, looking for feedback: If we want to support multiple grain clients in a given process/AppDomain calling into different clusters, then each Fully automatic/transparent association would be ideal: grain references could be passed between multiple clusters & client, and stored & retrieved with no intervention by the user. To illustrate how a fully automatic system could work @sergeybykov pointed out the extreme case where all of the information required to reconstruct the grain client is serialized along with each grain reference. Such a system would likely be too heavy in practice (grain references are supposed to be cheap). Another option is to only support automatic association when communicating references within a given cluster. This should support the 99% use-case where there is only one cluster. To implement this we would automatically associate grain references during deserialization - the deserializer would need context about the Under this option, we could adopt the following rules:
If a call is made on an unbound grain reference, we will throw a strongly typed exception. Because we do not always know which We could accomplish this using an API like so: var client = new GrainClient(config);
client.Initialize();
var user = mySerializer.Deserialize<IUserGrain>(serializedReferenceFromStorage);
client.BindGrainReference(user); // bind the user grain reference to the specified client.
// Alternative API using an IAddressable extension method:
user.BindGrainReference(client); Finally, the above system could be extended if each cluster had a unique id. In such a scenario, we could potentially create a map of id->client and use that map when deserializing each reference. When communicating references between grains/clients in the cluster they belong to, we could avoid serializing the cluster id and follow rule 1 above. Rule 2 would become the following:
If we adopt this extension then we can adopt an API to support binding a var clients =
new Dictionary<ClusterId, IRuntimeClient> { [clusterA] = clientA, [clusterB] = clientB, };
if (!grain.TryBindGrainReference(clients)) throw new Exception("!!!"); |
The scenario that makes me skeptical of the cluster ID direction is when the app persist a grain reference in storage, and reads it a month (or 12 months) later. The cluster ID would have to be an immutable variable in the deployment for this to work, and the cluster would have to be available at all times later. This makes me think that a more pragmatic solution is the manual binding one. Less magic, no implicit long term commitments to config variables like cluster ID. |
I'm all for it, especially initially. It's just worth noting that we could extend the concept to support auto binding in a wider range of scenarios in future. Side note: we can keep |
👍 identical to how I envisioned this too, with the exception of the bind method name (Yeah, that's how identical to my thoughts it was). I did also consider a few similar things especially with regards to the multi cluster support. Agree that it's an improvement that could be done later, since we should support a way to (re) bind manually anyway. |
@gabikliot I want to ensure that you have visibility into this, since you may have feedback on the proposed strategy discussed above. |
Sure, I will take a look. |
This issue is essentially resolved by #2822. There are still outstanding issues with regards to logging, metrics, and maybe some other classes being shared between instances. Multiple clients can be used in a single AppDomain, clients can be created and used from within silos. Work is underway to give Silos the same treatment with a 'silo builder' and that will hopefully include fixes to make logging & metrics non-global. SiloBuilder design is being discussed in #2936 IMO, we can close this issue and if there are specific areas which still need to be addressed then we can open issues for those. |
Connecting to multiple Orleans Silos from the same client is not possible because the Orleans client class is static and there can be only one of it in a process. Making the
GrainClient
non-static will help solving this issue.Client code will create an instance of
GrainClient
instead of using the staticGrainClient.Initialize
as follows:@gabikliot wrote:
TODOs:
RuntimeClient.Current.SendRequest
TraceLogger
instancesTraceLogger
The text was updated successfully, but these errors were encountered: