Skip to content

Typed Builder / state protocols: optimistic concurrency, and the writes that bypass the entity (ExecuteUpdate, metadata writes, raw SQL) #396

Description

@PhysShell

Описание

The state-protocol profile, and with it the TB-MVP-01 typed EF workflow, protects the local C# capabilities and aliases of one tracked entity instance. It explicitly does not protect the persisted row from the following.

  1. Concurrent writers. TB-MVP-01 registered concurrency as option A, out of scope: there is no concurrency token. Two requests that both load a Submitted order can both pass WithSubmitted and both save Approved. Two different transitions racing (approve vs. something else) are not claimed correct.

  2. Writes that bypass the entity's C# surface:

    • ExecuteUpdate/ExecuteDelete;
    • Entry(order).Property("Status").CurrentValue = …;
    • raw SQL;
    • another process;
    • reflection.

    These are stated limits, and they are pinned as fixtures that are accepted:

    • frontend/roslyn/protocol-samples/efcore/known-gaps/StateWrittenByBulkUpdate.cs.txt;
    • frontend/roslyn/protocol-samples/efcore/known-gaps/StateWrittenThroughChangeTracker.cs.txt;
    • samples/OrderBackend/corpus/limits/K2_execute_update.cs.txt.

Proposal, as two separable slices:

  • (a) Concurrency in the Typed Builder slice (product). Add a normal EF optimistic-concurrency token to the generated protocol, either [ConcurrencyCheck] on the state or a row version, and map DbUpdateConcurrencyException to a registered HTTP contract (e.g. 409 concurrent_transition). Acceptance needs a two-context conflict case: the second save loses and the row holds the first transition only. This was option B of TB-MVP-P24.
  • (b) Bypass detection (analysis). Decide whether the profile should flag ExecuteUpdate/SetProperty on protocol-owned state, string-keyed metadata writes of protocol-owned properties, and similar. If not, keep them as documented limits. Today they are accepted on purpose; turning them into refusals changes the profile's claim and needs a ruling.

Мотивация / сценарий

  • frontend/roslyn/README.md, "What is claimed": "It does not protect the persisted row from other ways of changing it… Those belong to concurrency tokens, constraints and transactions."
  • samples/OrderBackend/README.md opens with "Not claimed: concurrency".
  • docs/notes/tb-mvp-01-preregistration.md: concurrency option A.

A real backend runs requests concurrently, so (a) is the obvious next production gap of the typed workflow.

Альтернативы

  • Pessimistic locking or serializable transactions per transition. Provider-specific and heavier; optimistic tokens are the normal EF answer.
  • Do nothing and keep the explicit non-claim. That is honest, but it blocks "production-ready".

Область

tooling (scripts / CLI / CI)

Refs: #391 (TB-MVP-01), docs/notes/tb-mvp-01-report.md section "What the slice does not claim".

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions