Introduce entity work items and connect them to ITaskEntity definition.#186
Introduce entity work items and connect them to ITaskEntity definition.#186sebastianburckhardt merged 14 commits intofeature/entitiesfrom
Conversation
| /// orchestrators. Individual implementations of this contract may use it in different ways. The default | ||
| /// implementation does not use it. | ||
| /// </remarks> | ||
| bool TryCreateEntity( |
There was a problem hiding this comment.
Adding this is a breaking change. Easiest fix may be to add a new interface IDurableTaskFactory2 and add this there. Then consumers will need to cast to see if it implements the 2nd interface.
We can then consolidate down to single interface on next major version rev. Or even come up with a way to add new work item types without breaking changes to this interface.
There was a problem hiding this comment.
I have added an IDurableTaskFactory2.
Note that I haven't actually made the necessary changes to truly create the entities from whatever way they are annotated in the code. That is one of the open work items.
| for (int i = 0; i < operations.Operations!.Count; i++) | ||
| { | ||
| OperationRequest currentOperation = operations.Operations![i]; | ||
| this.operation.SetNameAndInput(currentOperation.Operation!, currentOperation.Input); |
There was a problem hiding this comment.
I would feel slightly better if the operation where immutable and it was new'd up each time. This is one of the reasons I split out the TaskEntityContext into its own object, so that it didn't need to new new'd up.
There was a problem hiding this comment.
This was a purposeful optimization to reduce allocations. From a code elegance perspective, using a new would obviously be nicer but I think we should try to execute the inner loop (operations in a batch) as efficiently as possible.
| /// <param name="dataConverter">The data converter.</param> | ||
| /// <param name="taskEntity">The task entity.</param> | ||
| /// <param name="entityId">The entity ID.</param> | ||
| public TaskEntityShim( |
There was a problem hiding this comment.
ctor can fit on one line I think (I keep to 120 col limit)
There was a problem hiding this comment.
It took me a bit to read and understand the commit/rollback logic here. At first I was surprised it was needed at all, but I get it now. Two suggestions for this:
- Add a lengthy comment somewhere explaining what it is and why it is needed. (IE: on exception we need to drop any performed actions and state changes).
- Code organization, consider the following:
- We want to roll back state & context, so lets add the rollback logic directly into those.
- The outer types
Commit()andRollback()methods simply callcontext.Commit(); state.Commit();andcontext.Rollback(); state.Rollback();respectively. No need for the outer class to understand what the exact commit/rollback logic is.
There was a problem hiding this comment.
FYI, this behavior is controllable via a parameter in DF (i.e. the rollback behavior can be turned off). I am wondering if we should try to honor this parameter here also. It adds complexity though so I would rather not (I am not sure how to even implement configuration settings).
This was the original discussion that led us to implement the rollback: Azure/azure-functions-durable-extension#1219
| { | ||
| // initialize/reset the state and action list | ||
| this.state.CurrentState = operations.EntityState; | ||
| this.context.Rollback(0); |
There was a problem hiding this comment.
If you go with the commit/rollback suggestion of mine, can make this a Reset().
There was a problem hiding this comment.
I have revised the Commit/Rollback/Reset.
| } | ||
| } | ||
|
|
||
| this.ClearCheckpoint(); // want to ensure the old state can be GC'd even if this shim is being cached |
There was a problem hiding this comment.
If we want to manage GC, maybe all the shim objects can be created at the start of ExecuteOperationBatchAsync and then let them go out of scope and be GC'd entirely.
I personally don't think optimizing to re-use these objects between batches is worth the added complexity.
There was a problem hiding this comment.
I think it is worth it if the batches are large and the operations are very short. For example, 10,000 increment operations on a counter. Reducing allocations is a pretty standard optimization goal for .NET code, and very typical for SDK design.
There was a problem hiding this comment.
The nice part here is that the user does not really see these optimizations, from the outside it looks clean.
There was a problem hiding this comment.
If you want to keep it the way it is, that is fine. Not my style, but I'll live 😄
Co-authored-by: Jacob Viau <javia@microsoft.com>
Co-authored-by: Jacob Viau <javia@microsoft.com>
Defines entity work items as a third work item type, and implements the necessary shim classes to connect it to ITaskEntity and the user-facing entity SDK.