-
Notifications
You must be signed in to change notification settings - Fork 1
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
all: TSS RPC Caller Service #40
Conversation
adding semicolons
…ransaction_hash ...also remove outgoing/incoming_status and have one status column
commit fb807aa Author: gouthamp-stellar <[email protected]> Date: Tue Sep 3 10:28:49 2024 -0700 remove the index on try_transaction_xdr and add column/index on try_transaction_hash ...also remove outgoing/incoming_status and have one status column commit 6fc0dc2 Author: gouthamp-stellar <[email protected]> Date: Tue Sep 3 08:58:46 2024 -0700 missing , commit a9cf4e3 Author: gouthamp-stellar <[email protected]> Date: Tue Sep 3 01:55:23 2024 -0700 make hash primary key instead of xdr commit c0f9d32 Author: gouthamp-stellar <[email protected]> Date: Fri Aug 30 15:18:27 2024 -0700 moving all migrations to one file commit 2de9898 Author: gouthamp-stellar <[email protected]> Date: Fri Aug 30 15:16:53 2024 -0700 adding semicolons adding semicolons commit 373c71a Author: gouthamp-stellar <[email protected]> Date: Fri Aug 30 15:12:24 2024 -0700 update commit 3f9f9f0 Author: gouthamp-stellar <[email protected]> Date: Fri Aug 30 15:12:00 2024 -0700 remove empty lines commit 9920f48 Author: gouthamp-stellar <[email protected]> Date: Fri Aug 30 15:06:40 2024 -0700 TSS tables and the channel interface commit a58d519 Author: gouthamp-stellar <[email protected]> Date: Fri Aug 30 10:55:22 2024 -0700 tables and interfaces for TSS
…and builds a transaction out of it
internal/tss/channels/utils.go
Outdated
if err != nil { | ||
return tss.RPCSendTxResponse{}, fmt.Errorf("%s: Unable to upsert try in tries table: %s", channelName, err.Error()) | ||
} | ||
if rpcErr != nil && rpcSendResp.Code.OtherCodes == tss.RPCFailCode || rpcSendResp.Code.OtherCodes == tss.UnMarshalBinaryCode { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be done before the 1st UpsertTry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to update the try with the rpcfailcode or unmarshallerrror code, which is why we call UpsertTry first before checking to see if there was an error
@@ -0,0 +1,21 @@ | |||
package services | |||
|
|||
import ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make channels and services one struct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Removed services, now only have channels and the router
internal/entities/rpc.go
Outdated
type RPCEntry struct { | ||
Key string `json:"key"` | ||
XDR string `json:"xdr"` | ||
LastModifiedLedgerSeq int64 `json:"lastModifiedLedgerSeq"` | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These won't be used anymore, we can clean them up. I had deleted them from the RPC Service PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeap, removed these so you can add them later
internal/serve/serve.go
Outdated
tssChannelConfigs := tsschannel.RPCCallerChannelConfigs{ | ||
TxManager: txManager, | ||
Store: store, | ||
MaxBufferSize: cfg.RPCCallerServiceChannelBufferSize, | ||
MaxWorkers: cfg.RPCCallerServiceChannelMaxWorkers, | ||
} | ||
rpcCallerServiceChannel := tsschannel.NewRPCCallerChannel(tssChannelConfigs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we initialize all services the same way for better readability? Same for the NewTransactionService
above.
tssChannelConfigs := tsschannel.RPCCallerChannelConfigs{ | |
TxManager: txManager, | |
Store: store, | |
MaxBufferSize: cfg.RPCCallerServiceChannelBufferSize, | |
MaxWorkers: cfg.RPCCallerServiceChannelMaxWorkers, | |
} | |
rpcCallerServiceChannel := tsschannel.NewRPCCallerChannel(tssChannelConfigs) | |
rpcCallerServiceChannel := tsschannel.NewRPCCallerChannel(tsschannel.RPCCallerChannelConfigs{ | |
TxManager: txManager, | |
Store: store, | |
MaxBufferSize: cfg.RPCCallerServiceChannelBufferSize, | |
MaxWorkers: cfg.RPCCallerServiceChannelMaxWorkers, | |
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeap, these are all being initialized the same now
func (r *router) Route(payload tss.Payload) error { | ||
var channel tss.Channel | ||
if payload.RpcSubmitTxResponse.Status.Status() != "" { | ||
switch payload.RpcSubmitTxResponse.Status.Status() { | ||
case string(tss.NewStatus): | ||
channel = r.RPCCallerChannel | ||
case string(entities.TryAgainLaterStatus): | ||
channel = r.ErrorJitterChannel | ||
case string(entities.ErrorStatus): | ||
if payload.RpcSubmitTxResponse.Code.OtherCodes == tss.NoCode { | ||
if slices.Contains(JitterErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | ||
channel = r.ErrorJitterChannel | ||
} else if slices.Contains(NonJitterErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | ||
channel = r.ErrorNonJitterChannel | ||
} else if slices.Contains(FinalErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | ||
channel = r.WebhookChannel | ||
} | ||
} | ||
default: | ||
// Do nothing for PENDING / DUPLICATE statuses | ||
return nil | ||
} | ||
} | ||
if channel == nil { | ||
return fmt.Errorf("payload could not be routed - channel is nil") | ||
} | ||
channel.Send(payload) | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 No problem with the logic, just an idea for improved readability:
func (r *router) Route(payload tss.Payload) error { | |
var channel tss.Channel | |
if payload.RpcSubmitTxResponse.Status.Status() != "" { | |
switch payload.RpcSubmitTxResponse.Status.Status() { | |
case string(tss.NewStatus): | |
channel = r.RPCCallerChannel | |
case string(entities.TryAgainLaterStatus): | |
channel = r.ErrorJitterChannel | |
case string(entities.ErrorStatus): | |
if payload.RpcSubmitTxResponse.Code.OtherCodes == tss.NoCode { | |
if slices.Contains(JitterErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | |
channel = r.ErrorJitterChannel | |
} else if slices.Contains(NonJitterErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | |
channel = r.ErrorNonJitterChannel | |
} else if slices.Contains(FinalErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | |
channel = r.WebhookChannel | |
} | |
} | |
default: | |
// Do nothing for PENDING / DUPLICATE statuses | |
return nil | |
} | |
} | |
if channel == nil { | |
return fmt.Errorf("payload could not be routed - channel is nil") | |
} | |
channel.Send(payload) | |
return nil | |
} | |
func (r *router) Route(payload tss.Payload) error { | |
switch payload.RpcSubmitTxResponse.Status.Status() { | |
case string(tss.NewStatus): | |
r.RPCCallerChannel.Send(payload) | |
case string(entities.TryAgainLaterStatus): | |
r.ErrorJitterChannel.Send(payload) | |
case string(entities.ErrorStatus): | |
if payload.RpcSubmitTxResponse.Code.OtherCodes == tss.NoCode { | |
if slices.Contains(JitterErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | |
r.ErrorJitterChannel.Send(payload) | |
} else if slices.Contains(NonJitterErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | |
r.ErrorNonJitterChannel.Send(payload) | |
} else if slices.Contains(FinalErrorCodes, payload.RpcSubmitTxResponse.Code.TxResultCode) { | |
r.WebhookChannel.Send(payload) | |
} else { | |
return fmt.Errorf("payload could not be routed, status %+v", payload.RpcGetIngestTxResponse.Status) | |
} | |
} | |
// Do nothing for PENDING / DUPLICATE statuses | |
case string(entities.PendingStatus), string(entities.DuplicateStatus): | |
return nil | |
default: | |
return fmt.Errorf("unexpected status %+v", payload.RpcGetIngestTxResponse.Status) | |
} | |
return nil | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is more readable, but the thing is, I want to be able to pass nil values for some/all channels. Because with the ingestor for example, it will only ever need the webhook channel. And if im passing nil values for these, I think I should explicitly check to see if the channels are nil before sending payloads to them
err = t.Store.UpsertTry(ctx, payload.TransactionHash, feeBumpTxHash, feeBumpTxXDR, rpcSendResp.Code) | ||
if err != nil { | ||
return tss.RPCSendTxResponse{}, fmt.Errorf("%s: Unable to upsert try in tries table: %s", channelName, err.Error()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UpsertTry
should likely be called after checking the previous errors, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because I want UpsertTry to capture the error code returned by SendTransaction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just two small new comments: about the %e
and the parseErr != nil
check
@@ -64,7 +64,7 @@ func (t *transactionManager) BuildAndSubmitTransaction(ctx context.Context, chan | |||
return rpcSendResp, fmt.Errorf("%s: RPC fail: %w", channelName, parseErr) | |||
} | |||
|
|||
if rpcErr != nil && rpcSendResp.Code.OtherCodes == tss.RPCFailCode || rpcSendResp.Code.OtherCodes == tss.UnmarshalBinaryCode { | |||
if parseErr != nil && rpcSendResp.Code.OtherCodes == tss.RPCFailCode || rpcSendResp.Code.OtherCodes == tss.UnmarshalBinaryCode { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case is impossible atm, isn't it? If parseErr != nil
it would fall into the previous check.
What
This is TSS's RPC Caller Service as described in this doc:
https://docs.google.com/document/d/1xcX86-w8lwT_60flCuYBK9X9co-108-5X6D9e5epw0U/edit#heading=h.76emp0zcbvdy
Why
This service is responsible for handling incoming transaction submission requests from clients and calling RPC (for the very first time) to submit those transactions to the network
Known limitations
N/A
Issue that this PR addresses
https://app.asana.com/0/1207947010297920/1208138733594316
Checklist
PR Structure
all
if the changes are broad or impact many packages.Thoroughness
Release