GemTalk / RemoteServiceReplication

MIT License
0 stars 3 forks source link

Snapshot fails by sending instVarAt: 0 due to GemStone class version skew #121

Open martinmcclure opened 2 years ago

martinmcclure commented 2 years ago

If you try to replicate a GemStone service whose class version is not the current version, mismatch of instance variable names can cause [] in RsrServiceSnapshot class >> reflectedVariablesFor:do: to send instVarAt: 0 to the service, which fails with an OffsetError.

This happens when the instance variable names of the template class (which is looked up by name, and thus always the current version) contains a name that does not name an instance variable in the class version actually being replicated.

Replicating non-current versions is likely to be problematic in any case, but should really only fail if the reflected instvars do not match on the two sides of the connection. I believe that error also fails with an easier-to-diagnose message.

One way to avoid this problem is to not resolve the template class by name, but instead search up the class hierarchy of the service until a class with the correct template class name is found. That solution would impose a limitation that the service actually be a kindOf: its template class, but I don't immediately see a situation where a situation that violated that constraint would be desirable. It would be currently possible, but a considerable amount of bother for little or no gain.

kurtkilpela commented 2 years ago

Instead, I suggest we pursue the idea of template registration.

If you wish to use a Service w/ RSR, you need to register the client and server classes under a template name. (See end of message for possible selectors.) The client and server classes would need to be related and share a common ancestor in the Service hierarchy. The common ancestor would server as the basis for computing the set of inst vars that are replicated. All inst vars below the common ancestor would be private.

When attempting to replicate a Service, we would ensure it has been registered. If it hasn't, we would signal an error locally.

When reifying a Service, if an compatable template has not been registered, we would signal an error remotely.

When classes change version, the existing registered version would continue to replicate. The new class version would error locally until it was properly registered.

registerTemplate: aTemplateSymbol
client: clientClass
server: serverClass

ensureTemplateRemoved: aTemplateSymbol

hasTemplate: aTemplateSymbol

clientForTemplate: aTemplateSymbol

serverForTemplate: aTemplateSymbol

template: aTemplateSymbol
ifAbsent: aBLock
"Returns an info holder containing the client, server, and details like the set of inst vars replicated"

templateForServiceClass: aServiceClass
ifAbsent: aBlock
"Returns an info holder containing the client, server, and details like the set of inst vars replicated"
martinmcclure commented 2 years ago

We would have to register a template on both sides of the connection before replication? With a new connection, how would service class registration be initiated on the server side?

A registration requirement adds significant complexity to using RSR, and I'm not seeing much benefit.

kurtkilpela commented 2 years ago

I wouldn't say 'significant'. In the past, we discussed this very mechanism as a way of supporting handshake mechanisms at the level of a Service.

The problem with the strategy of looking up classes by traversing their class hierarchy is that you could end up switching the class version. If you replicate a client, then the client gets garbage collected while the client is retained, then you replicate the server, it will have to restore to looking up the class as the Client instance won't exist.