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

Service Protocol V4 and Immutable journal #2476

Merged
merged 23 commits into from
Jan 24, 2025

Conversation

slinkydeveloper
Copy link
Contributor

@slinkydeveloper slinkydeveloper commented Jan 8, 2025

This PR implements the ServiceProtocol V4 and the immutable journal (often referred in the codebase as Journal V2 or Journal Table V2).

The Immutable Journal is a rework of the journal model, splitting commands and completions in distinct entries. The commit c484925 defines the new data model, which roughly works as follows:

  • The journal is composed of entries, which can be:
    • Commands (e.g. call, set state, etc)
    • Notifications
    • Events
  • Notifications are sub-categorized into:
    • Completions (what we used to write back in the entries)
    • Signals, which can be addressed with either a numeric id or a string

In order to implement the new protocol and the immutable journal, there are two places where most of the interesting stuff happens:

  • In the invoker, commit 4edf7d4 (@tillrohrmann PTAL).
  • In the state machine, commits c1616ca (@tillrohrmann PTAL) and 0e13883 and 5f1ae6f.
    • Notably, a lot of code was copy-pasted from the old state machine to the new state machine. This was done to reduce the risk of this changes and to make as obvious as possible the branching points between old and new state machine. All these branching points for the state machine are in the old state machine mod.rs file.
    • There are few new commands for the wal protocol that we don't write yet, but will be used in future releases once we remove the old service protocol.
    • Because the invoker is the component that ultimately decides the service protocol version, we initialize the journal table always using the old table, and then when the invoker sends the PinnedDeployment effect we perform, if needed, a migration from the old table to the new table. This enforces the following invariants:
      • if pinned service protocol is none or <= 3 then use old journal table, else use new journal table
      • For a given invocation id, either old journal table contains something, or new journal table contains something, but not both at the same time
    • The aforementioned invariant has two corner cases:
      • If we get an awakeable completion before the PinnedDeployment effect. To solve this case, I introduced a new id scheme called ExternalSignalIdentifier, which will be produced only by SDKs using service protocol v4.
      • If we get cancelled before the PinnedDeployment effect. In this case, the journal contains only the input entry, thus we can ignore the cancel for now.

The storage changes are minimal (commit 2ba04cc), they add a JournalTableV2 which is very similar to the old JournalTable, but uses the new data model and adds a reverse index from notification id to notification and from completion id to command.

There are few other code organization changes that have been made in this PR and will need subsequent work to finalize:

  • Sunsetting the https://github.com/restatedev/service-protocol and just move all that stuff here. We don't need to publish the proto files to BSR anymore, and there's no need to have a repo only for that, so it reduces maintenance burden to consolidate those protobuf files just here under /service-protocol.
  • Protobuf messages were moved to restate_types (presumably for the service protocol version data structure) but I would like to reverse this and simply generate the service protocol version data structure (or even just write it in code, no need to have this in protobuf), and will do it once we remove the old service-protocol.

This PR misses the following, which will be tackled in followups:

  • Wiring the new journal table to datafusion
  • Service protocol spec, which needs to be rewritten
  • Unit test coverage of the new state machine

@slinkydeveloper slinkydeveloper force-pushed the immutable-journal branch 7 times, most recently from d66ad00 to 64060ad Compare January 14, 2025 15:44
@slinkydeveloper slinkydeveloper changed the title [WIP] Immutable journal [WIP] Service Protocol V4 and Immutable journal Jan 14, 2025
@slinkydeveloper slinkydeveloper changed the title [WIP] Service Protocol V4 and Immutable journal Service Protocol V4 and Immutable journal Jan 14, 2025
@slinkydeveloper slinkydeveloper force-pushed the immutable-journal branch 3 times, most recently from a7f22ec to 7101298 Compare January 15, 2025 18:58
@slinkydeveloper
Copy link
Contributor Author

Good news! All the feature tests for protocol V4 on our WIP python SDK branch are passing!

@slinkydeveloper slinkydeveloper force-pushed the immutable-journal branch 3 times, most recently from de7778a to 59356bc Compare January 21, 2025 12:22
This contains the materialized data model `Entry` and the stored data model `RawEntry`
…ntroduce new ExternalSignalIdentifier used to complete awakeables created by journals using journal table V2.
…e contains the entry codec and the message codec of the new service protocol.

To simplify code generation, I also moved in a parent directory the service-protocol. Eventually we use this directory as ground truth of the protocol, and we sunset https://github.com/restatedev/service-protocol
* Add JournalTableV2, used for the new service protocol
* Expand InvocationStatus to hold, in the suspended state the _awaiting on notification_ information
* Add OutboxMessage::NotifySignal (this change is a bit pointless, see restatedev#2484)
* This adds few new effects, such as JournalEntryV2 and SuspendedV2 to carry the new journal info.
* The ServiceProtocolRunnerV4 is a copy of the previous ServiceProtocolRunner, but using the new message and entry types. There is no respective EntryEnricher for Journal V2, as it was a useless abstraction.
* The JournalReader interface can read both the old and the new journal. If the service protocol uses version 4, an in-flight migration of the input entry is executed by the ServiceProtocolRunnerV4
* Few changes were needed in the InvocationStateMachine to support the new cases to wait for retries, notably if we propose a run completion, then we need to wait for that to be pushed in the journal before retrying.
* Changes all the receivers to receive on StateMachineContext with self. This helps the new state machine for now, albeit we should remove all these methods in future.
* Added branching points with new state machine.
Copy link
Contributor

@igalshilman igalshilman left a comment

Choose a reason for hiding this comment

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

Tested this locally with the verification test. Mixed protocols v4 and v3.

@slinkydeveloper slinkydeveloper merged commit affc514 into restatedev:main Jan 24, 2025
14 checks passed
@slinkydeveloper slinkydeveloper deleted the immutable-journal branch January 24, 2025 18:42
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 this pull request may close these issues.

2 participants