Hi Stephen.
Thank you for the feedback. Regarding transactions, after I wrote the
letter, I am inclined to think that the approach using GraphTraversal that
we currently use is closer to what I want to see in the TinkerPop process
API than the steps designed to control TXs.
BTW, we use the autoExecute approach a lot :-)
/// Start a new transaction if it is not yet started and executes passed
> in code in it.
> ///
> /// If a transaction is already started, executes passed in code in it.
> In case of exception,
> /// rolls back the transaction and commits the changes if the
> transaction was started by this
> /// method.
> public <X extends Exception> void executeInTx(
> @Nonnull FailableConsumer<YTDBGraphTraversalSource, X> code) throws
> X {
> var tx = tx();
> YTDBTransaction.executeInTX(code, (YTDBTransaction) tx);
> }
/// Start a new transaction if it is not yet started and executes passed
> in code in it.
> ///
> /// If a transaction is already started, executes passed in code in it.
> In case of exception,
> /// rolls back the transaction and commits the changes if the
> transaction was started by this
> /// method.
> ///
> /// Unlike {@link #executeInTx(FailableConsumer)} also iterates over the
> returned
> /// [YTDBGraphTraversal] triggering its execution.
> public <X extends Exception> void autoExecuteInTx(
> @Nonnull FailableFunction<YTDBGraphTraversalSource,
> YTDBGraphTraversal<?, ?>, X> code)
> throws X {
> var tx = tx();
> YTDBTransaction.executeInTX(code, (YTDBTransaction) tx);
> }
/// Start a new transaction if it is not yet started and executes passed
> in code in it and then
> /// returns the result of the code execution.
> ///
> /// If a transaction is already started, executes passed in code in it.
> In case of exception,
> /// rolls back the transaction and commits the changes if the
> transaction was started by this
> /// method.
> public <X extends Exception, R> R computeInTx(
> @Nonnull FailableFunction<YTDBGraphTraversalSource, R, X> code)
> throws X {
> var tx = tx();
> return YTDBTransaction.computeInTx(code, (YTDBTransaction) tx);
> }
On Mon, Nov 24, 2025 at 1:44 PM Stephen Mallette <[email protected]>
wrote:
> Generally speaking, I think this idea begs to be explored but I also think
> that it's a change of extraordinary size that will need a lot of thought
> and planning to be sure it is done properly. I think initial efforts with
> that plan are already underway with 3.8.0 where it introduced the notion of
> StepContract interfaces and "step placeholders" which should allow
> providers to more easily provide their own implementations. In this way, a
> provider would be implementing at a Gremlin level rather than at that
> Structure API level. So, that's a starting point to allow for any of this
> to happen. I don't recall past discussions about what happens to Element
> interfaces, but I sense they would end up being read-only as you described.
> I suppose they would stay interfaces and there would be a few concrete
> TinkerPop implementations that we'd offer for providers to convert to when
> implementing steps. Remote providers might skip all that together and just
> write directly to GraphSON or GraphBinary.
>
> I don't know if transactions should explicitly be implemented as a
> traditional Step or not. They don't behave like steps in my mind, in that I
> don't see how they chain. Maybe it's more like a terminal step or a
> special step series like io().read()/write(). I think the first work to be
> taken around this big topic is to try to build consensus for what
> transactions look like, both as a part of the Gremlin language and the HTTP
> API. I know Ken has been thinking about the Transaction API for 4.x, but no
> formal proposal has been raised yet that I can recall.
>
> I will add that while I feel the Transaction API is a must-have for 4.x,
> I'm not sure that I see removal of the Graph API as a critical item for
> that version. If there was consensus on a plan to do so, I think it would
> be best for that to fall into a later body of work where perhaps the
> deprecation for the Graph API is in 4.x with removal in 5.x.
>
> On Sat, Nov 22, 2025 at 8:49 AM Andrii Lomakin via dev <
> [email protected]> wrote:
>
> > Dear like-minded colleagues,
> >
> > Sorry for the stream of ideas, but I wanted to share my thoughts on API
> > dual support.
> >
> > I believe the dual support of two API types—structured and process—is
> > counterproductive because it prevents the creation of truly
> > platform-independent distributions.
> > When an application development team begins to rely on the structured
> API,
> > they become limited to a minimal number of vendors who support embedded
> > deployments.
> >
> > Furthermore, I agree with Stephen Mallette that it is more
> straightforward
> > and more idiomatic for a provider to implement a few basic steps that
> > operate on database records than to implement the more demanding
> interface
> > of a Graph instance.
> >
> > In practice, this suggests the following changes:
> >
> > 1. Remove the Graph interface as a public API.
> > 2. Make the Element, Vertex, and Edge concepts read-only.
> > 3. Add steps to control transactions uniformly at the GraphTraversal
> level
> > to unify management.
> >
> > Regarding transaction management, the current implementation appears to
> be
> > an ununified side feature, especially considering the disparate
> lifecycles
> > between embedded and remote deployments. Introducing steps that control
> the
> > transaction lifecycle would resolve this issue.
> >
> > What do you think about these points?
> > We will consider implementing those items on our side in the short term.
> >
> > Best regards,
> > Andrii Lomakin
> > YouTrackDB development lead.
> >
>