juli pushed a commit to branch wip-goblinsify in repository shepherd. commit e8304f88f77053833e8a1d671d35ebe05c1a0490 Author: Juliana Sims <j...@incana.org> AuthorDate: Thu Oct 24 12:12:50 2024 -0400
Incorporate Spritely feedback into design doc --- goblins-port-design-doc.org | 65 ++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/goblins-port-design-doc.org b/goblins-port-design-doc.org index 98cfed7..c7aa26d 100644 --- a/goblins-port-design-doc.org +++ b/goblins-port-design-doc.org @@ -24,15 +24,15 @@ understanding the present discussion. * Design Description The Shepherd's current architecture already takes inspiration from the actor -model. As such, most of the work to be done is translation from the extant form -of actors to the Goblins form of actors. In general, Shepherd actors are +model. As such, most of the work to be done is translation from the extant +form of actors to the Goblins form of actors. In general, Shepherd actors are represented by a record type to hold state, a core procedure reading messages from a [[https://github.com/wingo/fibers][Fibers]] [[https://github.com/wingo/fibers/wiki/Manual#23-channels][channel]] in a loop, and procedures to send the appropriate messages. Sometimes the record type is unneeded and the core loop procedure manages all state internally. In this rewrite, we typically represent Goblins -actors with a combination of the [[https://spritely.institute/files/docs/guile-goblins/0.14.0/define_002dactor.html][~define-actor~]] macro and the [[https://spritely.institute/files/docs/guile-goblins/0.14.0/Methods.html][~methods~]] macro. -Immutable state is left in the constructor's closure to be referenced as though -a procedure argument while mutable state is stored in a [[https://spritely.institute/files/docs/guile-goblins/0.14.0/Cell.html][cell]]. +actors with a combination of the [[https://spritely.institute/files/docs/guile-goblins/0.14.0/define_002dactor.html][~define-actor~]] macro for the base actor and +the [[https://spritely.institute/files/docs/guile-goblins/0.14.0/Methods.html][~methods~]] macro to support multiple messages per actor, while [[https://spritely.institute/files/docs/guile-goblins/0.14.0/Cell.html][cell]]s are +used for values which change over time. What follows is a description of the expected major changes this port will bring about. It does not aim to be exhaustive, and it does not aim to be unyielding. @@ -54,7 +54,7 @@ As referenced above, both Goblins and the Shepherd use Fibers, a library implementing the communicating sequential processes (CSP) paradigm, to provide concurrency primitives. As Fibers implements it, this means creating fibers (delimited continuations) which communicate through channels which send -messages between fibers. When a fiber sends or receives a messages, its +messages between fibers. When a fiber sends or receives a message, its computation is suspended until another fiber is ready to receive or send the message. At this point the fibers are resumed to "rendezvous," exchange their message, and continue computation. @@ -64,8 +64,7 @@ message, and continue computation. Because Fibers is fundamentally a set of convenient but primitive abstractions over underling OS functionality, the Shepherd is responsible for creating and managing fibers when and as it needs them. Typically, communication between -actors happens in messages sent through channels which are frequently passed -back and forth, sometimes in messages sent over channels. +actors happens in messages sent through channels. Importantly, the Shepherd does not enable parallelism in its core fiber. Fibers builds parallelism on top of POSIX threads, which are incompatible with @@ -217,17 +216,22 @@ problems. ** Transactionality and Memory -Goblins transactionality compresses its ~transactormap~ objects to the same size -they would be even without the transactionality. Only the debugger causes -~bcom~ to grow memory. +Goblins provides transactionality, which raises the question of possible +memory growth. However, transactions are continuously merged after success +and therefore are not kept in memory by default. The exception is when +Goblins' "time-traveling debugger" is explicitly enabled, which is not the +case in production code. ** Code Inversion -Object-capability security inverts many ACL concepts of control flow and -authority as part of its security mechanisms. This can lead to unfamiliar code -and imitate the situation known as "callback hell." To mitigate this issue, the -~let-on~ macro exists, allowing traditional-looking Scheme code that expands to -ocaps-style ~on~. +Ocaps uses a promise and callback-based paradigm for asynchronicity that +inverts many synchronous concepts of control flow. This can lead to +unfamiliar code and imitate the situation known as "callback hell," familiar +to those who know promises from JavaScript. However, Goblins supports full +promises, including promise pipelining, so there is less need for chained +callbacks. Additionally, Goblins provides helpers when chained callbacks +cannot be avoided, such as the ~let-on~ which allows traditional-looking +Scheme code that expands to promise-handling ~on~. * Open Questions @@ -238,11 +242,12 @@ further consideration. Goblins message-passing over the network could theoretically result in a situation where a given vat is unable to accept more messages, but remote -actors don't know this -- or maliciously take advantage of this as part of an -attack. While this situation has never been encountered in practice, it is a -subject of active consideration within Spritely and the broader [[https://ocapn.org/][OCapN]] -community. It is beyond the design scope of the current project, but we -mention it to clarify that is something we are aware of. +actors may not (but should) know this -- or, of greater concern, maliciously +take advantage of this as part of an attack. While this situation has never +been encountered in practice, it is a subject of active consideration within +Spritely and the broader [[https://ocapn.org/][OCapN]] community. It is beyond the design scope of +the current project, but we mention it to clarify that is something we are +aware of. * Ocaps Appendix @@ -265,19 +270,19 @@ security guarantees can be made. ** Capabilities -In ocaps, a capability is simply a reference to an actor. On a local machine, -this takes the shape of a standard object reference in the host language -- -usually a pointer. Remote actors are usually represented by a local actor which -simply forwards messages to the actor itself. An actor can only receive -capabilities at creation, by creating the actor associated with the capability, -or by being given a capability in a message from another actor which already has -the capability. +In language-based ocaps, a capability is simply a reference to an actor. On a +local machine, this takes the shape of a standard object reference in the host +language -- usually a pointer. Remote actors are usually represented by a +local actor which simply forwards messages to the actor itself. An actor can +only receive capabilities at creation, by creating the actor associated with +the capability, or by being given a capability in a message from another actor +which already has the capability. ** Messages and Methods -Strictly speaking, Scheme function application is message-passing in Goblins. +Strictly speaking, Scheme function application is message handling in Goblins. However, idiomatic Goblins relies heavily on the [[https://spritely.institute/files/docs/guile-goblins/0.14.0/Methods.html][~methods~]] macro to allow actors -to accept multiple different messages. This macro produces a lambda accepting +to handle multiple different messages. This macro produces a lambda accepting as its first argument a method name, which is itself a symbol. These methods may then accept arguments as would any regular lambda.