Skip to content

[raft/store] Update Transact signature#1577

Open
MariemBaccari wants to merge 2 commits into
interuss:masterfrom
Orbitalize:change_transact_signature_prototype
Open

[raft/store] Update Transact signature#1577
MariemBaccari wants to merge 2 commits into
interuss:masterfrom
Orbitalize:change_transact_signature_prototype

Conversation

@MariemBaccari

@MariemBaccari MariemBaccari commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Transact currently takes a raw func(ctx, R) error closure which works for the sqlstore but can't be replicated by the Raftstore since it needs a request type, payload and an independently accessible function to execute on the apply side.

This PR changes the interface to accept a store.Action[R] instead in preparation for the raftstore implementation.
The interface function Execute should contain the current action (business logic) defined in the handlers.

To keep changes minimal in this PR, the FuncAction[R] adapter wraps the existing closures as a stub Action.
Follow-up PRs will remove FuncAction[R] and extract the actions for all handlers.

The PR also adds TransactWithResult[R, Res], a generic function wrapping Transact which serves as a helper for result type asserts to avoid code duplication on the handler side. The reason why we need a wrapper instead of making Transact generic is that Go does not currently allow generic methods.

@MariemBaccari MariemBaccari force-pushed the change_transact_signature_prototype branch 3 times, most recently from adc2bed to 558c48b Compare June 29, 2026 12:50
@barroco barroco added the dss-raft Relating to the application-layer consensus implemenation based on raft label Jun 29, 2026
@MariemBaccari MariemBaccari force-pushed the change_transact_signature_prototype branch 4 times, most recently from 5dcae06 to 373d538 Compare June 30, 2026 14:11
@MariemBaccari MariemBaccari force-pushed the change_transact_signature_prototype branch from 373d538 to 1c46a39 Compare July 1, 2026 07:56

@mickmis mickmis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IMO the newly added abstractions have room for improvement. They expose concepts that look too specific to an implementation. As suggested in a comment, consider pushing raft-specific logic into the raft code.

Comment thread pkg/store/store.go Outdated
Comment on lines +11 to +20
type Action[R any] interface {
ActionMetadata
Execute(ctx context.Context, r R) (any, error)
Payload() any
}

type ActionMetadata interface {
RequestType() string
IsReadOnly() bool
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • functions on those interface need to be documented correctly
  • it is unclear from this PR why we need a separate ActionMetadata interface

Comment thread pkg/store/store.go Outdated
return res, nil
}

type ActionAdapter[R any, T ActionMetadata] struct {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is this? It's not used anywhere, not described in PR description, and not documented. Remove it if not necessary?

Comment thread pkg/store/store.go Outdated
Transact(ctx context.Context, f func(context.Context, R) error) error
// Attempt to apply the operations in action to the R Repo it is supplied. All operations performed
// on the R Repo by action will be applied or rejected atomically.
Transact(ctx context.Context, action Action[R]) (any, error)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why does this get a new return parameter for the result? This looks like a new feature separate from the objective of this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

With the old closure-based signature, the handlers captured results through closure variables. With the change of signature, we don't have that anymore. The only way to return a result is through the return value of Transact itself. I think this change is inseparable from the parameter change as it's the consequence of it.

Comment thread pkg/store/store.go Outdated
Comment on lines +13 to +14
Execute(ctx context.Context, r R) (any, error)
Payload() any

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's a lot of any types. We'd like to avoid that in general, especially here both types are not unknown IIUC. This could indicate shaky abstractions.

Comment thread pkg/store/store.go Outdated
)

// Action represents a set of operations to be performed on a Repo type R.
type Action[R any] interface {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Naming: why not Transaction? This is what it is after all, a (store) transaction on a repository R.

Comment thread pkg/store/store.go Outdated

type ActionMetadata interface {
RequestType() string
IsReadOnly() bool

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Checking the other PR (#1580): I think I get why this is introduced here, but I think the abstractions can be improved. To me it looks like the payload, the request type, and the readonly flags are all functions of the DSS operation (i.e. the HTTP endpoint called). Given that, what about storing alongside the transaction function only the operation, and inferring all of the raft-specific details in the raft code?
That would also eliminate the additions to the generated code in #1580.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I just pushed another proposal that aims to implement your suggestion. We could pass Transact the restapi request directly and have a Dispatch function that maps restapi requests to their corresponding execution functions. You can refer to #1525 and #1582 to have an idea of the implications of this on both the raftstore and sqlstore implementations. #1582 implements the aux store using this design.
On the one hand, we eliminate the generated methods and the Action structs and interfaces, simplifying my initial proposal but on the other hand we lose the typing at the Transact signature...
What do you think ?

Comment thread pkg/store/store.go Outdated
f func(context.Context, R) error
}

func NewActionFunction[R any](f func(context.Context, R) error) *ActionFunction[R] {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good idea for the transition 👍

@MariemBaccari MariemBaccari force-pushed the change_transact_signature_prototype branch from 7df05ef to d700014 Compare July 6, 2026 11:17
@MariemBaccari MariemBaccari requested a review from mickmis July 6, 2026 12:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dss-raft Relating to the application-layer consensus implemenation based on raft

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants