Skip to content

Traditional Begin and Commit transactions support in websocketsΒ #36

@G4brym

Description

@G4brym

Is your feature request related to a problem? Please describe.
Traditional frameworks like Django rely heavily on sql transactions, like BEGIN; COMMIT; and ROLLBACK.

Recently, I've created a Django library called django-cf that allows developers to connect Django apps to both D1 HTTP API or to a Durable Object DB via another small project I've made.

In that project I've already implemented the "traditional" begin and commit functionality as I will be describing in this issue, and it works quite well and fast.
So I think it makes sense to bring such a feature to startbase πŸ˜„

This feature will allow startbase to grow even more, as this will open the door to other traditional frameworks to write startbase adapters to laravel, rails, and other. Django will already have a working driver, that i wrote.

Describe the solution you'd like
This feature involves modifying 2 key parts of the websocket implementation:

  • generating a unique id to new connections, and registering the new id with the connection using the tags api
  • adding 3 more actions

First, when a new connection is made, we must generate a unique id, usually uuid, and connecting this id with the socket using the tags api.
After this we will be able to identify the socket that is sending messages when a new one arrives.

Currently, startbase websocket messages, only expects messages with action=query
I'm proposing adding 3 more actions to the websocket implementation, called transaction.begin, transaction.commit and transaction.rollback
When the server receives a transaction.begin, we get the socket unique id, generated in the previous step and save that in a local variable inside the DO, as var 1 (name to decide).
We also record the current PITR into another variable locally, as var 2 (name to decide).
Note that both these variables must not be saved in the DO KV, because if the DO resets for some reason, the transaction status must be cleared.
From this point on, a new transaction is taking place, so when a server receives a message with action=query, we must check if the message is from the socket that sent the transaction.begin.
If this is true, we execute the query, otherwise, we must block the query, this can be done using timeouts, this way the query execution will just be delayed, until the transaction is cleared.

If the server receives a transaction.commit, we clear the var 1 and 2.
Clearing these variable, will allow other sockets that have sent queries while the DO was blocked, to start executing automatically.

If the server receives a transaction.rollback, we just need to rollback the DO to the recorded PITR saved in var 2 and trigger a object reset for the DO to be restarted.

Example implementation here
There are some small differences from the implementation described above, and the one in the link, but are very small, and i think the one described is better.

Additional context
I'm willing to make the pull request, I just want to get the project maintainers opinion and approval on the implementation, before starting

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions