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

Refactor the D1 binding to use D1DatabaseSession for all actions #2624

Merged
merged 7 commits into from
Sep 4, 2024

Conversation

lambrospetrou
Copy link
Contributor

@lambrospetrou lambrospetrou commented Aug 28, 2024

Overview

This change prepares the D1 binding for the upcoming Sessions API (relevant https://blog.cloudflare.com/building-d1-a-global-database). Most of the changes is moving things around, but the highlights are as below:

  1. A new D1DatabaseSession class is introduced that maintains a commitTokenOrConstraint property, and also takes ownership of the fetch+_send/_sendOrThrow methods.
    • This class proxies all calls to the D1 eyeball worker, and automatically adds the commit token as an HTTP header to the requests and extracts it from the response headers.
    • Our eyeball worker and the D1 DO will extract the commit token and accordingly decide which replica should route the requests to.
  2. There is a new D1DatabaseSessionAlwaysPrimary that extends D1DatabaseSession and essentially always sends the commit token constraint first-primary.
    • This session subclass also provides the existing dump, exec functions that the new Sessions API does not have.
  3. As specified by the SPEC, the default if no commit token is provided to the withSession() function is "first-unconstrained" (to run the first query (which may be a read or a write) with no constraints, and then use causal consistency for subsequent queries).

Notes

I decided to design it such that D1DatabaseSession proxies all the calls and maintains the commit token so that the other classes don't really care about which session they use, or having to know about it.

This way, all the complex logic about the commit token and how the interaction with the D1 DOs is going to be inside our eyeball worker, which we control fully, it's easier to deploy and fix, and is the first shared entrypoint with the REST API too, so once the REST API can pass the commit token to use, the rest of the logic is exactly the same.

I am not sure if using HTTP headers is common in Cloudflare to pass this kind of information to our APIs, so if that's not allowed/suggested, then we will need to pass it as query parameter instead.

Suggestions for naming of the header or the query parameter welcome.

Compatibility flag

There is a new experimental compatibility flag enable_d1_with_sessions_api to expose this new withSessions() method. The default binding still uses the D1DatabaseSession object though, so this PR's changes will actually be running after merge, always sending the first-primary constraint.

The d1-api-test.js is used by the D1 eyeball worker E2E tests so I added the new tests in a new test suite with the compatibility flag enabled only for that.

Tests

bazel run //src/cloudflare/internal/test/d1:d1-api-test
...
Executing tests from //src/cloudflare/internal/test/d1:d1-api-test
-----------------------------------------------------------------------------
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test:testWithoutSessions
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test:testWithoutSessions


bazel run //src/cloudflare/internal/test/d1:d1-api-test-with-sessions
...
Executing tests from //src/cloudflare/internal/test/d1:d1-api-test-with-sessions
-----------------------------------------------------------------------------
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test-with-sessions:test_d1_api_happy_path
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test-with-sessions:test_d1_api_happy_path
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_default
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_default
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_first_primary
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_first_primary
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_first_unconstrained
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_first_unconstrained
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_some_ranomd_token
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test-with-sessions:test_d1_api_happy_path_withsessions_some_ranomd_token
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test-with-sessions:test_d1_api_withsessions_old_token_skipped
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test-with-sessions:test_d1_api_withsessions_old_token_skipped
workerd/server/server.c++:3847: debug: [ TEST ] d1-api-test-with-sessions:test_d1_api_withsessions_token_handling
workerd/server/server.c++:3855: debug: [ PASS ] d1-api-test-with-sessions:test_d1_api_withsessions_token_handling

The first target runs the default database tests, without using the sessions API, and without the compatibility flag enabled.

The second target runs all the test suites with the compatibility flag enabled.

Copy link

github-actions bot commented Aug 28, 2024

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@lambrospetrou lambrospetrou changed the title [CFSQL-703] refactor the D1 binding to use D1DatabaseSession for all actions WIP - [CFSQL-703] refactor the D1 binding to use D1DatabaseSession for all actions Aug 28, 2024
@lambrospetrou lambrospetrou force-pushed the lambros/d1-replication-sessions-API-01 branch 3 times, most recently from 963937b to 11a0b48 Compare August 28, 2024 15:26
@lambrospetrou lambrospetrou changed the title WIP - [CFSQL-703] refactor the D1 binding to use D1DatabaseSession for all actions [CFSQL-703] refactor the D1 binding to use D1DatabaseSession for all actions Aug 28, 2024
@lambrospetrou lambrospetrou changed the title [CFSQL-703] refactor the D1 binding to use D1DatabaseSession for all actions [CFSQL-703][STOR-3690] refactor the D1 binding to use D1DatabaseSession for all actions Aug 28, 2024
@lambrospetrou lambrospetrou force-pushed the lambros/d1-replication-sessions-API-01 branch from 11a0b48 to 2382ee0 Compare August 29, 2024 11:22
@lambrospetrou lambrospetrou changed the title [CFSQL-703][STOR-3690] refactor the D1 binding to use D1DatabaseSession for all actions Refactor the D1 binding to use D1DatabaseSession for all actions Aug 29, 2024
@lambrospetrou
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

github-actions bot added a commit that referenced this pull request Aug 29, 2024
@lambrospetrou lambrospetrou force-pushed the lambros/d1-replication-sessions-API-01 branch 6 times, most recently from a970407 to acc1db4 Compare August 29, 2024 14:55
@lambrospetrou lambrospetrou marked this pull request as ready for review August 29, 2024 17:26
@lambrospetrou lambrospetrou requested review from a team as code owners August 29, 2024 17:26
@lambrospetrou lambrospetrou force-pushed the lambros/d1-replication-sessions-API-01 branch 3 times, most recently from 9e947e4 to a65f7b5 Compare August 30, 2024 16:16
Copy link
Contributor

@justin-mp justin-mp left a comment

Choose a reason for hiding this comment

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

I won't comment on the details of the code, but the class structure seems reasonable, especially how the statements use the session class.

src/cloudflare/internal/d1-api.ts Outdated Show resolved Hide resolved
src/cloudflare/internal/d1-api.ts Show resolved Hide resolved
src/cloudflare/internal/d1-api.ts Show resolved Hide resolved
src/cloudflare/internal/d1-api.ts Show resolved Hide resolved
Copy link
Collaborator

@geelen geelen left a comment

Choose a reason for hiding this comment

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

Looks good! A bit of feedback, but nothing major, so consider this approved.

src/cloudflare/internal/d1-api.ts Outdated Show resolved Hide resolved
src/cloudflare/internal/test/d1/d1-api-test.wd-test Outdated Show resolved Hide resolved
src/cloudflare/internal/d1-api.ts Show resolved Hide resolved
src/cloudflare/internal/d1-api.ts Outdated Show resolved Hide resolved
src/cloudflare/internal/d1-api.ts Show resolved Hide resolved
src/cloudflare/internal/d1-api.ts Outdated Show resolved Hide resolved
@lambrospetrou lambrospetrou force-pushed the lambros/d1-replication-sessions-API-01 branch 4 times, most recently from 106f99d to 629a599 Compare September 2, 2024 12:31
...values,
});

export async function testD1ApiQueriesHappyPath(DB) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was cut-pasted as-is, without any changes apart from adding the last section of DELETE statements, so that the database is cleaned up.

@lambrospetrou lambrospetrou force-pushed the lambros/d1-replication-sessions-API-01 branch from 629a599 to c74db2b Compare September 2, 2024 12:43
@lambrospetrou lambrospetrou force-pushed the lambros/d1-replication-sessions-API-01 branch from c74db2b to 4b1c31e Compare September 3, 2024 10:29
@lambrospetrou lambrospetrou merged commit 485a7ba into main Sep 4, 2024
13 checks passed
@lambrospetrou lambrospetrou deleted the lambros/d1-replication-sessions-API-01 branch September 4, 2024 09:04
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.

6 participants