Projekt

Obecné

Profil

Stáhnout (4.76 KB) Statistiky
| Větev: | Tag: | Revize:
1
using System.Diagnostics;
2
using System.Net.Http.Json;
3
using System.Text;
4
using System.Text.Json;
5
using System.Text.Json.Serialization;
6
using DiskQueue;
7
using LDClient.network.data;
8

    
9
namespace LDClient.network {
10
    public class ApiClient : IApiClient {
11
        
12
        public static readonly Payload ExampleInfo = new() {
13
            UserName = "honikCz",
14
            HostName = "Bramborak",
15
            TimeStamp = DateTime.Parse("2022-03-21 18:05:00.168895"),
16
            HeadDevice = new DebuggerInfo {
17
                SerialNumber = "C12345678912"
18
            },
19
            BodyDevice = new DebuggerInfo {
20
                SerialNumber = "C98765432198"
21
            },
22
            Status = ConnectionStatus.Connected
23
        };
24

    
25
        private bool _running;
26

    
27

    
28
        private readonly string _uri;
29
        private readonly HttpClient _client;
30
        private readonly IPersistentQueue _cache;
31
        private readonly uint _retryPeriod;
32
        private readonly uint _maxEntries;
33
        private readonly uint _maxRetries;
34
        
35

    
36

    
37
        public ApiClient(string url, uint port, string path, uint retryPeriod, uint maxEntries, uint maxRetries,
38
            string cacheFilename) {
39
            _uri = $"{url}:{port}{path}";
40
            _retryPeriod = retryPeriod;
41
            _maxEntries = maxEntries;
42
            _maxRetries = maxRetries;
43

    
44
            _client = new HttpClient();
45
            _cache = new PersistentQueue(cacheFilename);
46

    
47
        }
48

    
49
        public async Task SendPayloadAsync(Payload payload) {
50
            try {
51
                Stopwatch stopWatch = new();
52
                stopWatch.Start();
53
                
54
                var response = await _client.PostAsJsonAsync(_uri, payload, new JsonSerializerOptions {
55
                    Converters = {
56
                        new JsonStringEnumConverter( JsonNamingPolicy.CamelCase)
57
                    }
58

    
59
                });
60
                stopWatch.Stop();
61
                CreateRequestLog(payload, response, stopWatch.ElapsedMilliseconds);
62

    
63
                response.EnsureSuccessStatusCode();
64
            } catch (Exception e) {
65
                Program.DefaultLogger.Error($"Failed to send {payload} to the server. Due to: {e.Message}");
66
                CachePayload(payload);
67
            }
68
        }
69

    
70
        private static void CreateRequestLog(Payload payload, HttpResponseMessage response, long durationMs) {
71
            var responseToLog = new {
72
                statusCode = response.StatusCode,
73
                content = response.Content,
74
                headers = response.Headers,
75
                errorMessage = response.RequestMessage,
76
            };
77

    
78
            Program.DefaultLogger.Info($"Request completed in {durationMs} ms,\n" +
79
                                 $"Request body: {payload},\n" +
80
                                 $"Response: {responseToLog}");
81
        }
82
        
83

    
84
        private async Task ResendPayloadsAsync() {
85
            var numberOfPayloadsToResend = Math.Min(_maxRetries, _cache.EstimatedCountOfItemsInQueue);
86
            var payloads = new List<Payload>();
87

    
88
            using (var session = _cache.OpenSession()) {
89
                for (var i = 0; i < numberOfPayloadsToResend; i++) {
90
                    var rawBytes = session.Dequeue();
91
                    var payload = JsonSerializer.Deserialize<Payload>(rawBytes);
92
                    if (payload is not null) {
93
                        payloads.Add(payload);
94
                    }
95
                }
96
                session.Flush();
97
            }
98

    
99
            if (payloads.Count > 0) {
100
                Program.DefaultLogger.Debug($"ResendPayloadAsync -> {payloads.Count} unsent payloads");
101
                var tasks = new List<Task>();
102
                foreach (var payload in payloads) {
103
                    Program.DefaultLogger.Info($"Resending {payload}.");
104
                    tasks.Add(SendPayloadAsync(payload));
105
                }
106
                await Task.WhenAll(tasks);
107
            }
108
        }
109

    
110

    
111
        private void CachePayload(Payload payload) {
112
            Program.DefaultLogger.Info($"Storing {payload} into the cache.");
113
            var numberOfCachedPayloads = _cache.EstimatedCountOfItemsInQueue;
114
            using var session = _cache.OpenSession();
115
            if (numberOfCachedPayloads >= _maxEntries) {
116
                session.Dequeue();
117
            }
118
            var payloadJson = JsonSerializer.Serialize(payload);
119
            session.Enqueue(Encoding.UTF8.GetBytes(payloadJson));
120
            session.Flush();
121
        }
122

    
123
        public async void Run() {
124
            Program.DefaultLogger.Info("Api Client thread has started");
125
            _running = true;
126
            while (_running) {
127
                await ResendPayloadsAsync();
128
                Thread.Sleep((int)_retryPeriod);
129
            }
130
        }
131

    
132
        public void Stop() {
133
            _running = false;
134
        }
135
    }
136
}
(1-1/2)