Skip to content

Conversation

@akantsevoi
Copy link
Contributor

No description provided.

@dkorolev
Copy link
Contributor

dkorolev commented Jan 9, 2025

Good progress!

Here are my major thoughts, in no particular order.

(I'm in the mode of focusing on alignment between us two and @AdamEther, not in the mode of reviewing this change to merge it in yet. That is, I want to merge it, but not until we agree what the clean solution should look like, first conceptually, and then in code.)

First of all, I think the good old OOP ideas are alive and well, and doubly so if we are eventually looking in the direction of CRDTs. So the code snippet that uses "get" followed by "modify" and "put" reads ... not modern enough to my taste. What would read better if we have the data type defined for the persisted object (a "data class" if you wish), that has:

  • Data fields,
  • Serialization techniques from various and to various formats and storages (perhaps autogenerated, but they need to be present),
  • Notions of which field are OLTP-friendly (i.e. can be accessed as they are in the "strongly consistent OLTP state"), and which are still in the process of being populated by "long-playing" maroon daemons.
  • Modifiers, i.e. instead of alice.balance -= V, bob.balance += V we do alice.Charge(V) and bob.Deposit(V). YMMV, but this syntax is not only cleaner, it also sets us for success later on as some operations can and will be parallelized.
  • Also, constructors from previous version(s) of the object, for zero-downtime schema evolution.

In a way, you have exactly this: combinedStore.transfers.create(Transfer{ ... }) in the comment! Perhaps I'd even go "all Haskell" and say that instead of methods in class definitions we may have (durable!) data types for mutation requests, such as Transfer, and static checking that the very object that needs to be processing this object has the respective function defined -- at compile time.

Secondly, I understand the difference between "API endpoints" and maroon daemons, as well as their relative priority. But here's the thing: an "API call" may well require some "maroon" processing!

My understanding (and yes, we did not talk about this in detail, and I'm happy to be convinced otherwise) is that the distinction should not be as clear. In a way, kicking off migration is also calling an API endpoint :-)

For have O(1) guarantees, I was just thinking of some yield construct, similar to JavaScript's nextTick() wrapped into "maroon await". That solves the problem once and for all, doesn't it? I would then even go further and say that we can default all while loops (and perhaps even the for ones) to the ones that do yield after every iteration. In other words, there can be sync for (...) { } and durable for (...) { }, and just for (...) would be the durable version. What do you think?

@akantsevoi
Copy link
Contributor Author

But here's the thing: an "API call" may well require some "maroon" processing!
But here's the thing: an "API call" may well require some "maroon" processing!
kicking off migration is also calling an API endpoint :-)

+100500

I touched it slightly on:

in order to support these long-term scenarious we should be able to automatically slice our long-term scenarious into a sequence of correct/pausable "short O(1)" operations

We will come here! I was thinking about it as a "more advanced" scenario. Wanted to clarify the easier one first.

For have O(1) guarantees, I was just thinking of some yield construct, similar to JavaScript's nextTick() wrapped into "maroon await".

I think that's really good. Haven't thought about it. I mean that "just" a syntax sugar. BUUUUT, it might make the code way more readable and easier to analyze and build some guarantees.
Same about special cases for loops(like in rust as an example). Specific loops can be analyzed differently. Like it.

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