-
Notifications
You must be signed in to change notification settings - Fork 137
Persist agreed quotes in RFQ service #1863
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
base: 0-8-0-staging
Are you sure you want to change the base?
Conversation
3c33ca3 to
f0acc02
Compare
Pull Request Test Coverage Report for Build 19272717740Details
💛 - Coveralls |
Pull Request Test Coverage Report for Build 19038516198Details
💛 - Coveralls |
98bcb62 to
5a2bd52
Compare
| } | ||
|
|
||
| // DeactivatePolicy marks the given RFQ policy as inactive. | ||
| func (s *PersistedPolicyStore) DeactivatePolicy(ctx context.Context, |
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.
why do we need for this to be a db query?
We can retrieve active quotes by validating the expiry field. This way we won't have to store an explicit active flag.
While the daemon is running, quotes which expire within the runtime can be deleted directly in-memory without any db calls. On the next start up, they will never be loaded again.
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.
As far as I understand, it is possible to get new quotes for the same (SCID, policy_type) (where policy_type is either sale or purchase). In which case we need to deactivate (aka soft delete) the old quotes so we only have a single active quote per (SCID, policy_type). Does this make sense?
| if err := m.restorePersistedPolicies(ctx); err != nil { | ||
| return fmt.Errorf("error restoring persisted RFQ "+ | ||
| "policies: %w", err) | ||
| } |
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.
I think this should happen in m.orderHandler.Start. Effectively, I think PolicyStore should only be accessible by OrderHandler.
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.
I think we have the same idea but this is currently not possible with the current architecture (unless we do 2 DB requests) , see my comment below. This is because localAcceptedBuyQuotes and localAcceptedSellQuotes are in the Manager so to populate both the Manager and OrderHandler we need to fetch the policies
IMO we should have a single store that handles storage (in-memory + DB) so the entire notion of "restoring" is hidden to the business (Manager and OrderHandler) and happens automatically when the store is instantiated. The Store is then injected in the business and we interact with it simply by calling exposed methods without knowing how the data is stored.
Happy to refactor this.
| buyAccepts, sellAccepts, err := m.cfg.PolicyStore.FetchActivePolicies( | ||
| ctx, | ||
| ) | ||
| if err != nil { | ||
| return fmt.Errorf("error fetching persisted policies: %w", err) | ||
| } |
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.
method m.cfg.PolicyStore.FetchActivePolicies should be called FetchLocalAcceptedQuotes or something like that?
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.
I think even m.localAcceptedBuyQuotes shouldn't be in the manager. But maybe we can fix that later.
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.
I tried not to refactor the current architecture but I agree the current storage in the manager is not ideal and I wanted to change that as well.
We are currently storing data directly inside the Manager using a bunch of SyncMap as an in-memory storage/cache. OrderHandler also has its own in-memory storage and now we are adding persistent storage in the form of a store (PolicyStore), but all storage should be encapsulated away and injected. The Manager or OrderHandler don't care whether we are using in-memory, an external DB or an hybrid.
IMO the solution is to move the entirety of the storage to one or multiple stores that are injected into the corresponding components so we can get rid of all the SyncMap and expose interfaces. We can keep the subscribers and groupKeyLookupCache in the manager to avoid over-engineering.
It's out of the scope of this PR but I can work on refactoring this if needed.
Adds a new rfq_policies table and store allowing persistence of sale and purchase policies. Exposes functions to deactivate currently active policies upon inserting, fetching or manually.
5a2bd52 to
f7ebd34
Compare
RFQ buy/sell accepts are now written to the database (
rfq_policiestable) whenever a policy is agreed, giving us an audit trail and keeping quotes across restarts.The
OrderHandlerreloads these rows at startup to rebuild policies and the manager repopulates its in-memory caches from the same data.Added a check in
itestthat restarts Bob’stapdmid RFQ flow and verifies the quote remains available to Carol.Fixes #855