Skip to content

Introduce entity work items and connect them to ITaskEntity definition.#186

Merged
sebastianburckhardt merged 14 commits intofeature/entitiesfrom
entities-entities
Sep 14, 2023
Merged

Introduce entity work items and connect them to ITaskEntity definition.#186
sebastianburckhardt merged 14 commits intofeature/entitiesfrom
entities-entities

Conversation

@sebastianburckhardt
Copy link
Member

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.

/// orchestrators. Individual implementations of this contract may use it in different ways. The default
/// implementation does not use it.
/// </remarks>
bool TryCreateEntity(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

@sebastianburckhardt sebastianburckhardt Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ctor can fit on one line I think (I keep to 120 col limit)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. 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).
  2. Code organization, consider the following:
    1. We want to roll back state & context, so lets add the rollback logic directly into those.
    2. The outer types Commit() and Rollback() methods simply call context.Commit(); state.Commit(); and context.Rollback(); state.Rollback(); respectively. No need for the outer class to understand what the exact commit/rollback logic is.

Copy link
Member Author

@sebastianburckhardt sebastianburckhardt Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you go with the commit/rollback suggestion of mine, can make this a Reset().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

@sebastianburckhardt sebastianburckhardt Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

@sebastianburckhardt sebastianburckhardt Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nice part here is that the user does not really see these optimizations, from the outside it looks clean.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@sebastianburckhardt sebastianburckhardt merged commit 2878163 into feature/entities Sep 14, 2023
@sebastianburckhardt sebastianburckhardt deleted the entities-entities branch September 14, 2023 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants