-
Notifications
You must be signed in to change notification settings - Fork 208
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
durable Kinds forget state property names across upgrade, are inconsistent when init() adds more #4935
Comments
I like putting it in the kind. Rather than a list, lets talk about using a copyRecord pattern as schema. |
On further thought, the most uniform approach would be to supply the names in Supplying it in Although.. if the list is always present in
So there's a clear contradiction: we need to deserialize It also tells me that upgrading the schema is going to be tricky: we may already have deserialized instances by the time v2 can tell us that it wants to change the property lists. We could conceivably disallow local durable objects from |
Aye. What does userspace need to write? I'm hoping there's a syntax which adds as few characters as possible to To get myself unblocked (so I can give you a working vat upgrade sooner), I may start by adding a plain list of strings to |
The |
I guess the counterbalance would be: what can we do with that extra information, especially if we get it early (during definition, rather than waiting for the first instance to be created). The wouldn't-it-be-cool vision is a SQLite table definition, if that would give us some extra-efficient storage/indexing/lookup functionality. We could probably defer building the There's probably also an argument to be made about forcing userspace to be up-front about their data structures, and providing the schema on a definition call, rather than having us glean it from |
Well that sounds like a leak which would allow to discover if your representative was created before or after another instance was inited ... I would first like to clarify our intent, along the lines of @warner's question above: do we or don't we want to support If all objects of a kind should have the same state shape, then the shape definition shouldn't be done through implicit extraction from a dynamic instance creation. I hear @FUDCo's concern about repetition, and I'm wondering if there'd be a way to build the |
This is an aggressively-dynamic way to deal with virtual-object state property names. It allows each instance to have an entirely different set. I think we want something more static/pre-declared, but this approach unblocks my work on vat-upgrade and doesn't require changing any externally-visible API. We can replace it with a more static approach later. refs #4935
This is an aggressively-dynamic way to deal with virtual-object state property names. It allows each instance to have an entirely different set. I think we want something more static/pre-declared, but this approach unblocks my work on vat-upgrade and doesn't require changing any externally-visible API. We can replace it with a more static approach later. refs #4935
I'm working on getting #1848 upgrade working, and I've got a test that creates a durable Kind (and handle) in v1, creates an exports an instance, gets upgraded, the v2 code re-defines that kind (using the handle from baggage), then tries to invoke a method on a durable object. The
defineDurableKind
part works ok, but when I try to invoke the method, it fails because thestate
object is empty: no property getters/setters.I think there are some significant problems in
defineKindInternal
. There's apropertyNames
Set that lives in RAM, scoped todefineKindInternal
(so one per Kind). TheSet
is populated bymakeNewInstance
as it walks the properties of the initial state (as returned by the user-providedinit
function). It looks like thisadd
happens for every call toinit
. That means the properties we track could grow over time, if the user'sinit
function doesn't return a consistent set of properties.When we make a Representative,
makeRepresentative
uses thispropertyNames
Set to create thewrappedState
object: it makes one getter/setter pair per property name inpropertyNames
. That means the wrapper will grow new properties over time based upon the lastinit
that took place, unrelated to the properties that were stored for that particular instance. That's inconsistent at best, probably crashy if some behavior function tries toget()
a property that some other instance invented but which has no state on this instance (it'll try tom.unserialize(null)
, which isn't capdata), and feels like it might enable an ambient communication channel between unrelated instances (but one that probably needs the Kind's behavior functions to help, which doesn't count).The problem that affects Durables is that when we start the vat back up in a new version, we need to be able to thaw out these instances in a heap that has never seen an
init
. We can't rely upon userspace to tell us what the property names are. Instead, we must either store the property names in the DB at some point, or we need to build getters/setters for each Representative based upon the state stored on that instance (which means we need to fetch the state duringmakeRepresentative
, to at least read the.keys()
on it).Storing the property names in the DB makes the most sense, but it's a bit awkward that we don't learn what they are until the first
init
is called. But not impossibly awkward. The DB will have most of the description of the Kind as soon asdefineKind
is called, but the.statePropertyNames
key will be empty until the first instance is created. Then the key will be populated, and all subsequentinit
calls are obligated to use the same names. We can hold the property names in RAM too, for performance during the remainder of that version.When
defineKindInternal
is called, it needs to use thekindID
to look up the stored list of property names. If present, it should be loaded into RAM, used to define the getters/setters, and imposed upon allinit
calls. If missing, the nextinit
call should be used to populate it (and save to DB). In the missing case, we don't need the list for getters/setters because we know there aren't any instances yet.One other option (I think we discussed this a while ago) might be to require userspace to declare the state property names they're going to use, when calling
makeKindHandle
. Then we could store the property names in thekindDescriptor
DB key. That would be simple and elegant for the implementation, but maybe a bit clunky for userspace, which would see two lists of property names: one inmakeKindHandle
, the other in theirinit
function.OTOH, storing the list in the
kindDescriptor
would both force all instances to have the same schema, and preclude version-2 from augmenting the schema (which feels like a more significant restriction). I know @FUDCo has thought a lot about lazy/immediate DB upgrades (the usual "read v1, write v2" upgrade-when-touched approach), but we haven't really talked as a group about schema changes.@FUDCo thoughts? @erights could we get away with requiring
makeKindHandle(tag, [ ...statePropertyNames ])
? I think I prefer the simplicity of it, and if we don't have an obvious way to handle new property names anyways, then we might has well be more strict now, and find a way to relax the rules later on.The text was updated successfully, but these errors were encountered: