Skip to content

Commit

Permalink
Merge branch 'main' into nextII
Browse files Browse the repository at this point in the history
  • Loading branch information
jirikostiha committed Nov 2, 2024
2 parents f8357e1 + 57da88a commit 80dee57
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 45 deletions.
3 changes: 2 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ For usage see [example code](./src/SystemTests/Program.cs ), [official page](htt

## Changelog

2.5.20 various refactoring, improvements
2.5.19 various refactoring, minor fixes and changes, unit tests
2.5.18 XApiClient as main api providing class
2.5.17 time arguments instead of long, reduced memory footprint (long->int)
2.5.16 async cancelation, time members, various small changes
2.5.16 async cancellation, time members, various small changes
2.5.15 async streaming subscriptions, async IStreamingListener, various simplifications
2.5.14 replaced Newtonsoft.Json by System.Text.Json (pkamphuis)
2.5.13 support custom handling of exceptions in streaming connector, enriched exceptions
Expand Down
45 changes: 28 additions & 17 deletions src/SyncAPIConnector/ApiConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
// Redirected?.Invoke(this, new(endpoint));

// if (IsConnected)
// Disconnect();
// await DisconnectAsync(cancellationToken).ConfigureAwait(false);

// Endpoint = endpoint;
// await ConnectAsync(cancellationToken).ConfigureAwait(false);
Expand All @@ -184,17 +184,11 @@ public JsonObject ExecuteCommand(BaseCommand command)
{
var request = command.ToJsonString();

long currentTimestamp = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
long interval = currentTimestamp - _lastCommandTimestamp;
// If interval between now and last command is less than minimum command time space - wait
if (interval < CommandDelay.TotalMilliseconds)
{
Thread.Sleep((int)(CommandDelay.TotalMilliseconds - interval));
}
EnforceCommandDelay();

CommandExecuting?.Invoke(this, new(command));
var response = Connector.SendMessageWaitResponse(request);
_lastCommandTimestamp = currentTimestamp;
_lastCommandTimestamp = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;

var parsedResponse = JsonNode.Parse(response)
?? throw new InvalidOperationException("Parsed command response is null.");
Expand All @@ -208,6 +202,17 @@ public JsonObject ExecuteCommand(BaseCommand command)
}
}

private void EnforceCommandDelay()
{
long currentTimestamp = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;
long interval = currentTimestamp - _lastCommandTimestamp;

if (interval < CommandDelay.TotalMilliseconds)
{
Thread.Sleep((int)(CommandDelay.TotalMilliseconds - interval));
}
}

/// <summary>
/// Executes given command and receives response (withholding API inter-command timeout).
/// </summary>
Expand All @@ -220,17 +225,12 @@ public async Task<JsonObject> ExecuteCommandAsync(BaseCommand command, Cancellat
{
var request = command.ToJsonString();

long currentTimestamp = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
long interval = currentTimestamp - _lastCommandTimestamp;
// If interval between now and last command is less than minimum command time space - wait
if (interval < CommandDelay.TotalMilliseconds)
{
await Task.Delay((int)(CommandDelay.TotalMilliseconds - interval), cancellationToken);
}
await EnforceCommandDelayAsync();

CommandExecuting?.Invoke(this, new(command));
var response = await Connector.SendMessageWaitResponseAsync(request, cancellationToken).ConfigureAwait(false);
_lastCommandTimestamp = currentTimestamp;
_lastCommandTimestamp = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;


var parsedResponse = JsonNode.Parse(response);
if (parsedResponse is null)
Expand All @@ -246,6 +246,17 @@ public async Task<JsonObject> ExecuteCommandAsync(BaseCommand command, Cancellat
}
}

private async Task EnforceCommandDelayAsync()
{
long currentTimestamp = DateTimeOffset.Now.Ticks / TimeSpan.TicksPerMillisecond;
long interval = currentTimestamp - _lastCommandTimestamp;

if (interval < CommandDelay.TotalMilliseconds)
{
await Task.Delay((int)(CommandDelay.TotalMilliseconds - interval));
}
}

/// <inheritdoc/>
public void Disconnect()
{
Expand Down
2 changes: 1 addition & 1 deletion src/SyncAPIConnector/SyncAPIConnect.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<PackageProjectUrl>https://github.com/jirikostiha/xtb-xApi</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<SignAssembly>False</SignAssembly>
<Version>2.5.19</Version>
<Version>2.5.20</Version>
<Authors>Jiri Kostiha</Authors>
<PackageIcon>package_icon.png</PackageIcon>
</PropertyGroup>
Expand Down
10 changes: 8 additions & 2 deletions src/SystemTests/AsyncTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ namespace Xtb.XApi.SystemTests;

public sealed class AsyncTest : XApiClientTestBase
{
public AsyncTest(XApiClient client, string user, string password, string? messageFolder = null)
: base(client, user, password, messageFolder)
public AsyncTest(XApiClient client, string user, string password)
: base(client, user, password)
{
}

public async Task RunAsync(CancellationToken cancellationToken)
{
if (ShallLogTime)
Time.Start();

await ConnectionStage(cancellationToken);
await AuthenticationStage(cancellationToken);
await AccountInfoStage(cancellationToken);
Expand All @@ -26,6 +29,9 @@ public async Task RunAsync(CancellationToken cancellationToken)
await TradingStage(cancellationToken);
await TradingStage(cancellationToken);
await TradingHistoryStage(cancellationToken);

if (ShallLogTime)
Time.Stop();
}

public async Task ConnectionStage(CancellationToken cancellationToken)
Expand Down
22 changes: 15 additions & 7 deletions src/SystemTests/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ internal static class Program

private static void Main(string[] args)
{
using (var connector = new Connector(DemoRequestingEndpoint))
{
RunConnectorTest(connector);
}
//using (var connector = new Connector(DemoRequestingEndpoint))
//{
// RunConnectorTest(connector);
//}

Console.WriteLine();
//Console.WriteLine();

using (var xApiClient = XApiClient.Create(DemoRequestingEndpoint, DemoStreamingEndpoint))
{
Expand Down Expand Up @@ -58,15 +58,23 @@ private static void RunSyncTest(XApiClient xApiClient)
{
Console.WriteLine();
Console.WriteLine("----Sync test---");
var syncTest = new SyncTest(xApiClient, _userId, _password, @"\messages\");
var syncTest = new SyncTest(xApiClient, _userId, _password)
{
ShallLogTime = true
};
syncTest.Run();
}

private static void RunAsyncTest(XApiClient xApiClient)
{
Console.WriteLine("----Async test---");
Console.WriteLine("(esc) abort");
var asyncTest = new AsyncTest(xApiClient, _userId, _password);
var asyncTest = new AsyncTest(xApiClient, _userId, _password)
{
MessageFolder = @"\messages\",
ShallLogTime = true
};

using var tokenSource = new CancellationTokenSource();

var keyWaitTask = Task.Run(() =>
Expand Down
10 changes: 8 additions & 2 deletions src/SystemTests/SyncTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ namespace Xtb.XApi.SystemTests;

public sealed class SyncTest : XApiClientTestBase
{
public SyncTest(XApiClient client, string user, string password, string? messageFolder = null)
: base(client, user, password, messageFolder)
public SyncTest(XApiClient client, string user, string password)
: base(client, user, password)
{
}

public void Run()
{
if (ShallLogTime)
Time.Start();

ConnectionStage();
AuthenticationStage();
AccountInfoStage();
Expand All @@ -25,6 +28,9 @@ public void Run()
TradingStage();
TradingStage();
TradingHistoryStage();

if (ShallLogTime)
Time.Stop();
}

public void ConnectionStage()
Expand Down
28 changes: 23 additions & 5 deletions src/SystemTests/TestBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Threading.Tasks;
using Xtb.XApi.Responses;

Expand All @@ -13,6 +15,12 @@ protected TestBase(string user, string password)

protected Credentials Credentials { get; set; }

public bool ShallLogTime { get; set; }

public int ActionExecutionDelay { get; set; }

public Stopwatch Time { get; } = new();

protected static void Stage(string name)
{
var oc = Console.ForegroundColor;
Expand All @@ -23,27 +31,37 @@ protected static void Stage(string name)
Console.ForegroundColor = oc;
}

protected static void Action(string name)
protected void Action(string name)
{
Task.Delay(200);
Task.Delay(ActionExecutionDelay);
if (ShallLogTime)
Console.Write(Time.Elapsed);

Console.Write($" {name}...");
}

protected static void Pass(BaseResponse? response = null)
protected void Pass(BaseResponse? response = null)
{
var oc = Console.ForegroundColor;

if (response is null || response.Status == true)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("OK");
Console.Write("OK ");
}
else
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine($"Error: {response.ErrCode}, {response.ErrorDescr}");
Console.Write($"Error: {response.ErrCode}, {response.ErrorDescr} ");
}

if (ShallLogTime)
{
Console.ForegroundColor = oc;
Console.Write(Time.Elapsed);
}

Console.WriteLine();
Console.ForegroundColor = oc;
}

Expand Down
30 changes: 21 additions & 9 deletions src/SystemTests/XApiClientTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,12 @@ namespace Xtb.XApi.SystemTests;

public abstract class XApiClientTestBase : TestBase
{
protected XApiClientTestBase(XApiClient client, string user, string password, string? messageFolder = null)
private string? _messageFolder;

protected XApiClientTestBase(XApiClient client, string user, string password)
: base(user, password)
{
Client = client;
MessageFolder = messageFolder;

if (messageFolder != null)
{
Client.ApiConnector.Connector.MessageReceived += Connector_MessageReceived;
Client.ApiConnector.Connector.MessageSent += Connector_MessageSent;
}
}

private void Connector_MessageSent(object? sender, MessageEventArgs e)
Expand All @@ -39,7 +34,24 @@ private void Connector_MessageReceived(object? sender, MessageEventArgs e)
}
}

protected string? MessageFolder { get; set; }
public string? MessageFolder
{
get => _messageFolder;
set
{
_messageFolder = value;
if (value == null)
{
Client.ApiConnector.Connector.MessageReceived -= Connector_MessageReceived;
Client.ApiConnector.Connector.MessageSent -= Connector_MessageSent;
}
else
{
Client.ApiConnector.Connector.MessageReceived += Connector_MessageReceived;
Client.ApiConnector.Connector.MessageSent += Connector_MessageSent;
}
}
}

protected XApiClient Client { get; set; }

Expand Down
2 changes: 1 addition & 1 deletion src/SystemTests/Xtb.XApi.SystemTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<AnalysisLevel>latest-recommended</AnalysisLevel>
<OutputType>Exe</OutputType>
<IsPackable>false</IsPackable>
<Version>2.5.19</Version>
<Version>2.5.20</Version>
</PropertyGroup>

<ItemGroup>
Expand Down

0 comments on commit 80dee57

Please sign in to comment.