Skip to content
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

Consider a zone.slot() abstraction #2397

Open
mhofman opened this issue Aug 2, 2024 · 2 comments
Open

Consider a zone.slot() abstraction #2397

mhofman opened this issue Aug 2, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@mhofman
Copy link
Contributor

mhofman commented Aug 2, 2024

What is the Problem Being Solved?

We have a pattern for zone that emerged: prepareFoo(zone, 'foo', ...) for simple entries in a zone. If Foo requires complex (aka multiple prepared entries), it can create a subzone with that name. In some case that leaks onto the "prepare" function itself, which accepts a zone without a tag, assuming it's getting a subzone it ca take over.

However the current prepare pattern is a break in encapsulation: it effectively gives access to the full zone, but relies on the prepareFunction to pinky swear it will only write keys at the provided tag.

This has come up repeatedly in async-flow / orchestration design and similar issues were raised before, e.g. in Agoric/agoric-sdk#7107 (comment)

Description of the Design

Introduce a zone.slot(name) API with methods to define an exo or map/subzone in that slot, or create a sub slot (working as a series of prefixes which are joined when inserting the element).

slot.exoClass would no longer require a tag as that comes from the slot itself.

Prepare functions would be updated to only accept slots instead of zone + tag (or zone alone).

The current zone.exo(tag, ...args) would become an alias for zone.slot(tag).setExo(...args), and zone.subzone(tag) is effectively the equivalent of zone.slot(tag).setSubzone(). (prefix set to be bikeshed, but it should convey only a single type of thing can be stored there).

Security Considerations

This allows for better encapsulation of zones when passing them around.

Scaling Considerations

Slots can be heap only as they're transient objects representing an attenuated zone entry.

Test Plan

TBD

Compatibility Considerations

We may need some helper for prepare functions to remain backward compatible with the version accepting zone + tag (and maybe even just zone).

const prepareFoo = withZoneAndTagCompatibility((slot, arg1, arg2) => { ... });

Upgrade Considerations

New methods on existing APIs, adopt at own convenience.

@mhofman mhofman added the enhancement New feature or request label Aug 2, 2024
@gibson042
Copy link
Contributor

Before bikeshedding on specific names, can you clarify the "zone" data model and how this proposes to extend it? I haven't looked in a while, but my understanding is we're starting from something like "each subZone corresponds with a MapStore in its parent zone, and exos/stores in a zone correspond with entries in its MapStore":

flowchart TD
    Baggage[baggage: DurableMapStore] -->|makeDurableZone#40;baggage, baseLabel = 'durableZone'#41;| RootZone[rootZone: DurableZone#40;baggage#41;]
    RootZone -->|subZone#40;'foo'#41;| MakeFoo[/subBaggage = provideDurableMapStore#40;baggage, 'foo'#41;/]
    MakeFoo -->|makeDurableZone#40;subBaggage, `durableZone.foo`#41;| Foo[foo: DurableZone#40;baggage.get#40;'foo'#41;#41;]
    RootZone -->|subZone#40;'bar'#41;| MakeBar[/subBaggage = provideDurableMapStore#40;baggage, 'bar'#41;/]
    MakeBar -->|makeDurableZone#40;subBaggage, `durableZone.bar`#41;| Bar[bar: DurableZone#40;baggage.get#40;'bar'#41;#41;]
    Foo -->|subZone#40;'baz'#41;| MakeBaz[/subBaggage = provideDurableMapStore#40;subBaggage, 'baz'#41;/]
    MakeBaz -->|makeDurableZone#40;subBaggage, `durableZone.bar.baz`#41;| Baz[baz: DurableZone#40;baggage.get#40;'bar'#41;.get#40;'baz'#41;#41;]
    Baz -->|exo#40;'Qux'#41;| MakeQux[/provide#40;subBaggage, 'Qux_kindHandle', …#41;/]
    MakeQux --> Qux[Qux: Exo#40;baggage.get#40;'bar'#41;.get#40;'baz'#41;.get#40;'Qux_kindHandle'#41;#41;]
    Baz -->|exo#40;'Quux'#41;| MakeQuux[/provide#40;subBaggage, 'Quux_kindHandle', …#41;/]
    MakeQuux --> Quux[Qux: Exo#40;baggage.get#40;'bar'#41;.get#40;'baz'#41;.get#40;'Quux_kindHandle'#41;#41;]

Loading

@mhofman
Copy link
Contributor Author

mhofman commented Aug 2, 2024

I am not proposing to change the data structure. But to change the API:

flowchart TD
    Baggage[baggage: DurableMapStore] -->|makeDurableZone#40;baggage, baseLabel = 'durableZone'#41;| RootZone[rootZone: DurableZone#40;baggage#41;]
    RootZone -->|slot#40;'foo'#41;.setSubZone#40;#41;| MakeFoo[/subBaggage = provideDurableMapStore#40;baggage, 'foo'#41;/]
    MakeFoo -->|makeDurableZone#40;subBaggage, `durableZone.foo`#41;| Foo[foo: DurableZone#40;baggage.get#40;'foo'#41;#41;]
    RootZone -->|slot#40;'bar'#41;.setSubZone#40;#41;| MakeBar[/subBaggage = provideDurableMapStore#40;baggage, 'bar'#41;/]
    MakeBar -->|makeDurableZone#40;subBaggage, `durableZone.bar`#41;| Bar[bar: DurableZone#40;baggage.get#40;'bar'#41;#41;]
    Foo -->|slot#40;'baz'#41;.setSubZone#40;#41;| MakeBaz[/subBaggage = provideDurableMapStore#40;subBaggage, 'baz'#41;/]
    MakeBaz -->|makeDurableZone#40;subBaggage, `durableZone.bar.baz`#41;| Baz[baz: DurableZone#40;baggage.get#40;'bar'#41;.get#40;'baz'#41;#41;]
    Baz -->|slot#40;'Qux'#41;.setExo#40;#41;| MakeQux[/provide#40;subBaggage, 'Qux_kindHandle', …#41;/]
    MakeQux --> Qux[Qux: Exo#40;baggage.get#40;'bar'#41;.get#40;'baz'#41;.get#40;'Qux_kindHandle'#41;#41;]
    Baz -->|slot#40;'Quux'#41;.setExo#40;#41;| MakeQuux[/provide#40;subBaggage, 'Quux_kindHandle', …#41;/]
    MakeQuux --> Quux[Qux: Exo#40;baggage.get#40;'bar'#41;.get#40;'baz'#41;.get#40;'Quux_kindHandle'#41;#41;]

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants