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

Saga Transactions in Portals, Design Choice #44

Closed
jspenger opened this issue Feb 20, 2023 · 1 comment · Fixed by #52
Closed

Saga Transactions in Portals, Design Choice #44

jspenger opened this issue Feb 20, 2023 · 1 comment · Fixed by #52

Comments

@jspenger
Copy link
Member

jspenger commented Feb 20, 2023

I managed to get a first version of Saga-transactions working with nested Portals over the weekend. However, there is a potential downside to the current solution. There are two ways which we could go about this, I think both have pros / cons. We should decide on one of them to continue.

Both solutions allow a task to act both as a requester and as a replier, that is, it can send asks to some portal, but it can also handle requests and reply from another (or potentially the same portal).

1

We allow a task to call "reply" from within an "await" block. The flow which could cause this between Tasks A, B, C is the following:
A -- Ask --> B
B -- Receive Ask --
B -- Ask --> C
B -- Await --
C -- Receive Ask --
C -- Reply --
B -- Receive Reply, Exec Continuation --
B -- Reply Within Continuation --
A -- Receive Reply, ... ---

The problem with this first approach is that we need to save together with the Continuation also the Context from the Ask that caused the Continuation, this would include identifying information on the Asking-Key, Task, Workflow. This information may be somewhat heavy to keep for every continuation.

On the bonus side, this allows us to express in a nice way the flow of messages.

In this first model, we can express a Saga transaction as an unfolding sequence of requests, for which each link in the chain will pre-commit to the transaction. Once this chain has reached its end, each task can commit, and fold back by calling "reply" from within the continuation.

2

The second approach does not allow the continuation to capture the ask-handling-context, that is, it should not be possible to "reply" from within a "continuation" block.

This has the obvious benefit that we do not need to keep track of the asking context together with the continuation.

On the downside, this limits the expressivity of the model. In particular, we cannot express the Saga pattern anymore by simply allowing Tasks to Requesting, Awaiting the response, and Replying.

In this second model we can still express Saga transactions, however in a style akin towards programming with typed actors. The requester can together with its request also send a "replyTo" address; to replyer can save this replyTo address to some local state, such that it can reply back to the corresponding address later, when needed. Indeed, doing this we can emulate this unfolding and folding sequence of pre-commit and commits. However, it will be less natural (not via request/reply), but via request/request-to-reply-address.

TL;DR

The first option 1) allows us to express the Saga pattern naturally as request/reply steps; this, however, requires us to capture information about the caller in the continuation (potentially inefficient). Whereas 2) allows us to express the Saga pattern as we would in a typed Actor model without a reply function (for this we need to submit the reply address in the message); this may be more efficiently handled by the runtime, but perhaps more awkward to program. Personally, I think that we could go with 1.

@jspenger jspenger mentioned this issue Mar 7, 2023
6 tasks
@jspenger
Copy link
Member Author

After some deliberations it seems that option (1) which allows nesting replies within asks is the better option for now. The reason for preferring (1) is that it allows us to delegate the handling of a request to another replier. Without this pattern, if we used strategy (2), we would not be able to respond back to a requester if the requester does not expose a portal itself. It seems like a bad idea to force every requester to expose a portal, in addition, this forces either that the service needs to explicitly connect to this requester's portal beforehand, or to somehow dynamically connect to the requester's portal, both of which are bad options. This is why we should opt for (1) for now. It will come with some overhead on the data carried by events, but can some of the overhead can be mitigated in the runtime through various optimizations.

jspenger added a commit that referenced this issue Mar 13, 2023
* Implements nesting for portals, such that requests and replies can be nested within continuations
* Closes #44 
* Implements bank account example from #4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant