Skip to content
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

Merged
merged 75 commits into from
Oct 9, 2024
Merged

all: TSS RPC Caller Service #40

merged 75 commits into from
Oct 9, 2024

Conversation

gouthamp-stellar
Copy link
Contributor

@gouthamp-stellar gouthamp-stellar commented Sep 15, 2024

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

  • It is not possible to break this PR down into smaller PRs.
  • This PR does not mix refactoring changes with feature changes.
  • This PR's title starts with name of package that is most changed in the PR, or all if the changes are broad or impact many packages.

Thoroughness

  • This PR adds tests for the new functionality or fixes.
  • All updated queries have been tested (refer to this check if the data set returned by the updated query is expected to be same as the original one).

Release

  • This is not a breaking change.
  • This is ready to be tested in development.
  • The new functionality is gated with a feature flag if this is not ready for production.

adding semicolons
…ransaction_hash

...also remove outgoing/incoming_status and have one status column
commit fb807aa
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
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 <goutham.patnaikuni@stellar.org>
Date:   Tue Sep 3 08:58:46 2024 -0700

    missing ,

commit a9cf4e3
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
Date:   Tue Sep 3 01:55:23 2024 -0700

    make hash primary key instead of xdr

commit c0f9d32
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
Date:   Fri Aug 30 15:18:27 2024 -0700

    moving all migrations to one file

commit 2de9898
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
Date:   Fri Aug 30 15:16:53 2024 -0700

    adding semicolons

    adding semicolons

commit 373c71a
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
Date:   Fri Aug 30 15:12:24 2024 -0700

    update

commit 3f9f9f0
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
Date:   Fri Aug 30 15:12:00 2024 -0700

    remove empty lines

commit 9920f48
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
Date:   Fri Aug 30 15:06:40 2024 -0700

    TSS tables and the channel interface

commit a58d519
Author: gouthamp-stellar <goutham.patnaikuni@stellar.org>
Date:   Fri Aug 30 10:55:22 2024 -0700

    tables and interfaces for TSS
@gouthamp-stellar gouthamp-stellar changed the base branch from main to transaction_module September 23, 2024 00:29
@gouthamp-stellar gouthamp-stellar changed the base branch from transaction_module to main September 23, 2024 00:38
@gouthamp-stellar gouthamp-stellar changed the base branch from main to transaction_module September 23, 2024 00:38
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 {
Copy link
Contributor Author

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?

Copy link
Contributor Author

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 (
Copy link
Contributor Author

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

Copy link
Contributor Author

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

Base automatically changed from transaction_module to main September 25, 2024 03:40
Comment on lines 21 to 25
type RPCEntry struct {
Key string `json:"key"`
XDR string `json:"xdr"`
LastModifiedLedgerSeq int64 `json:"lastModifiedLedgerSeq"`
}
Copy link
Member

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.

Copy link
Contributor Author

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 Show resolved Hide resolved
internal/serve/serve.go Outdated Show resolved Hide resolved
internal/serve/serve.go Outdated Show resolved Hide resolved
Comment on lines 194 to 200
tssChannelConfigs := tsschannel.RPCCallerChannelConfigs{
TxManager: txManager,
Store: store,
MaxBufferSize: cfg.RPCCallerServiceChannelBufferSize,
MaxWorkers: cfg.RPCCallerServiceChannelMaxWorkers,
}
rpcCallerServiceChannel := tsschannel.NewRPCCallerChannel(tssChannelConfigs)
Copy link
Member

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.

Suggested change
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,
})

Copy link
Contributor Author

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

internal/tss/channels/rpc_caller_channel.go Outdated Show resolved Hide resolved
Comment on lines +61 to +89
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
}
Copy link
Member

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:

Suggested change
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
}

Copy link
Contributor Author

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

internal/tss/services/transaction_manager.go Outdated Show resolved Hide resolved
Comment on lines +58 to +61
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())
}
Copy link
Member

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?

Copy link
Contributor Author

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

internal/tss/store/store.go Outdated Show resolved Hide resolved
Copy link
Member

@daniel-burghardt daniel-burghardt left a 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 {
Copy link
Member

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.

@gouthamp-stellar gouthamp-stellar merged commit dd833aa into main Oct 9, 2024
5 checks passed
@gouthamp-stellar gouthamp-stellar deleted the rpc_caller_service branch October 9, 2024 02:31
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