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

Lt 5012 eod borders #516

Merged
merged 15 commits into from
Mar 26, 2024
Merged

Lt 5012 eod borders #516

merged 15 commits into from
Mar 26, 2024

Conversation

gponomarev-lykke
Copy link

No description provided.


namespace MarginTrading.Backend.Core.Services
{
public interface ISnapshotMonitor
Copy link
Member

Choose a reason for hiding this comment

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

The goal of this interface is suspicious.
3 methods change the state of snapshot and the last one checks if snapshot creation should be retried. I think too much responsibilities here for a single interface.

/// If snapshot is not created after a specified amount of time, SnapshotMonitorService will retry this operation
/// </summary>

public TimeSpan SnapshotCreationTimeout { get; set; } = TimeSpan.FromMinutes(5);
Copy link
Member

Choose a reason for hiding this comment

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

Reading the comment, I have a feeling this is retry timeout. Shouldn't you call it then CreationRetryTimeout or something?

public TimeSpan MonitoringDelay { get; set; } = TimeSpan.FromSeconds(30);

/// <summary>
/// If snapshot is not created after a specified amount of time, SnapshotMonitorService will retry this operation
Copy link
Member

Choose a reason for hiding this comment

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

either

Suggested change
/// If snapshot is not created after a specified amount of time, SnapshotMonitorService will retry this operation
/// If snapshot is not created after a specified amount of time, creation will be retried

or

Suggested change
/// If snapshot is not created after a specified amount of time, SnapshotMonitorService will retry this operation
/// If snapshot is not created after a specified amount of time, <see cref="SnapshotMonitorService"/> will retry this operation

public void SnapshotFinished()
{
_state = DraftSnapshotState.None;
_timestamp = default;
Copy link
Member

Choose a reason for hiding this comment

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

Obviously, you expect monitor to be reused. In this case, probably, there should be a guard against not proper usage of it. For example, currently, I can call SnapshotRequested and then SnapshotFinished. Which seems not right.

Copy link
Author

Choose a reason for hiding this comment

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

Good point, I'll think about it


namespace MarginTrading.Backend.Services
{
public class SnapshotMonitorService : BackgroundService
Copy link
Member

Choose a reason for hiding this comment

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

I can’t spot even semantically the difference between SnapshotMonitor and SnapshotMonitorService but obviously they are different classes.

Copy link
Author

Choose a reason for hiding this comment

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

SnapshotMonitorService cannot be injected into other services, as it implements IHostedService and is registered by AddHostedService.

SnapshotMonitor is responsible for tracking snapshot's state, and determines if timeout has expired and we need to retry the snapshot's creation process.

SnapshotMonitorService is a hosted service that is responsible for repeatedly checking the state of the SnapshotMonitor instance, and actually calling the snapshot's creation method (implemented in ISnapshotService)

Copy link
Member

@tarurar tarurar Mar 20, 2024

Choose a reason for hiding this comment

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

Your comment explains a lot, however it is not clear from the naming. Naming is similar and confuses. Next time someone reads the code, her or she will probably not have your comments unless specifically requested.

try
{
await _snapshotService.MakeTradingDataSnapshot(command.TradingDay, command.OperationId);
var quotes = await _quotesApi.GetCfdQuotes(command.TradingDay);
Copy link
Member

Choose a reason for hiding this comment

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

As I see this creates an ugly dependency on BookKeeper which becomes circular dependency cause bookkeeper already consumes trading core APIs.

Copy link
Author

@gponomarev-lykke gponomarev-lykke Mar 20, 2024

Choose a reason for hiding this comment

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

Kinda, and it creates some startup issues as described in the comment about IsAlive. But since BookKeeper handles the quotes and actually stores them in its database, I think it's responsible for them and must be a single source of truth.

Previous implementations managed this in two ways:

  • "missed" eod method simply pushed quotes into mt core api. This breaks the CreateSnapshotCommand handler, because there's no way to get quotes (we need to save them into a table inside mtcore, which leads to duplication)
  • "normal" eod would send quotes one-by-one via rabbitmq. This breaks the "missed" eod flow, because quotes would update internal caches of MtCore, and we should not send these outdated quotes and replace "normal" ones

My approach unifies both flows:

  • BookKeeper is responsible for quotes.
  • The CreateSnapshotCommand handler receives quotes from bookkeeper's IQuotesApi for both missed and normal flows, based only on TradingDay
  • During normal eod flow quotes are still being sent one-by-one and MtCore's caches are updated properly
  • During missed eod flow quotes are not being sent one-by-one, and MtCore's caches are not being broken by them

Copy link
Member

Choose a reason for hiding this comment

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

Do you have an estimate how much space the EOD quotes consume? Is it feasible/make sense to send them using message/command?

Copy link
Author

Choose a reason for hiding this comment

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

It heavily depends on load. The object itself is not that big:

        "Id": "BUGS2402",
        "Timestamp": "2024-03-21T21:29:26.6565081Z",
        "Bid": 112.0,
        "Ask": 112.0
    },

But if scaled to thousands of assets, it might become a bottleneck. I was thinking that I could add this data to CreateSnapshotCommand, but in the end decided against it.

The api in bookkeeper, on the other hand, can be refactored to return paginated response, and that is more scalable.

I think we can ship the current solution to the bank, and discuss it internally with Andrey A and Daniel when you return from vacation. I understand that it's controversial, and together we can come up with a better idea.

Copy link

Code Coverage

Package Line Rate Branch Rate Complexity Health
MarginTrading.Backend 3% 7% 598
MarginTrading.Backend.Core 66% 58% 1515
MarginTrading.SqlRepositories 0% 0% 469
MarginTrading.AzureRepositories 4% 36% 197
MarginTrading.Contract 0% 100% 38
MarginTrading.Backend.Contracts 34% 25% 582
MarginTrading.Backend.Core.Mappers 0% 0% 4
MarginTrading.Common 16% 16% 406
MarginTrading.Backend.Services 43% 38% 3319
Summary 36% (5885 / 16179) 34% (1484 / 4335) 7128

@gponomarev-lykke gponomarev-lykke merged commit 73d3cee into master Mar 26, 2024
1 check passed
@gponomarev-lykke gponomarev-lykke deleted the LT-5012-eod-borders branch March 26, 2024 10:47
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.

3 participants