[API BREAKING] wait_for follow up fixes #173
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This contains several follow ups to #111 around improving correctness, performance, and API ergonomics of the use of
wait_forwith a block condition. This is equivalent to the await method in Go and Java SDKs (Go docs).Split wait_for into dedicated methods
The
wait_formethod on workflow context started as a way to wait on a single future to complete. It was rarely called directly because activity or timer futures have their own.waitmethods that called through to this method. With the introduction of a conditional block towait_for, this signature became much more complicated, taking both a splat of futures and a conditional block. Note this is API breaking because thewait_formethod is going away. This method should rarely be called for activities and timers since futures already have an equivalentwaitmethod. The use ofwait_forwith a condition block or with wait-for-any semantics will need to be rewritten using the new methods.With this split, it is now two methods:
wait_for_anywhich takes a splat of futures, and blocks workflow progression until at least one future is completed. This is similar to the already existingwait_for_all.wait_untilwhich takes a block, and blocks until that block evaluates to true. Complex combinations of futures and workflow state can be combined into a single conditional block. For example, waiting on a timer firing or a signal being received can be done with something like,Deterministically order wildcard dispatch handlers
When
wait_untilis called, a dispatch function is added to resume the fiber once the condition has been satisfied. Because this condition could change due to any workflow progress, it must be evaluated on every dispatch. Before this change, these were always evaluated after any targeted dispatch callbacks (such as from a specific activity or timer). This can cause non-determinism in certain somewhat corner cases. These callbacks should always be called in the same order. This is achieved by associating an autoincrementing, unique ID with each handler. When the list of handlers is concatenated and filtered, it is now sorted by these IDs, guaranteeing order across replays.Remove dispatch handlers once they're no longer needed
In activities with long histories, the number of dispatch handlers can get quite large. Particularly for workflows that call
wait_untilmany times (such as in a loop), the number of these can get very large, and they must be invoked on every dispatch. This can cause performance problems that result in timed out workflow tasks. The fix in this change removes these once they're no longer needed. The unique autoincrementing ID mentioned in the previous section is used to identify and remove callbacks once they are no longer needed, dramatically improving performance for workflows with long histories.