Skip to content

Commit 7358ccb

Browse files
committed
fix ws reconnect
1 parent 592158f commit 7358ccb

3 files changed

Lines changed: 80 additions & 130 deletions

File tree

src/HuaJiBot.NET.Adapter.OneBot/ForwardWebSocketClient.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ internal class ForwardWebSocketClient
1010
private readonly WebsocketClient _client;
1111
internal readonly OneBotApi Api;
1212

13-
public ValueTask ConnectAsync()
14-
{
15-
return ValueTask.CompletedTask;
16-
}
13+
public ValueTask ConnectAsync() => _client.ConnectAsync();
1714

1815
public ForwardWebSocketClient(OneBotAdapter service, string wsUrl, string? token)
1916
{

src/HuaJiBot.NET.Adapter.Satori/Protocol/SatoriEventClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal class SatoriEventClient
2222
private readonly Timer _pingTimer;
2323
private readonly SatoriAdapter _service;
2424

25-
public Task ConnectAsync() => Task.CompletedTask;
25+
public async Task ConnectAsync() => await _client.ConnectAsync();
2626

2727
public SatoriEventClient(SatoriAdapter service, Uri wsUrl, string token)
2828
{

src/HuaJiBot.NET/Websocket/WebsocketClient.cs

Lines changed: 78 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
using System.Net.WebSockets;
22
using System.Text;
3-
using Microsoft.Extensions.Logging;
3+
using HuaJiBot.NET.Logger;
44
using Newtonsoft.Json.Linq;
55
using WatsonWebsocket;
6-
using ILogger = Microsoft.Extensions.Logging.ILogger;
76

87
namespace HuaJiBot.NET.Websocket;
98

@@ -16,9 +15,7 @@ public class WebsocketClient : IWebsocketClient
1615
private readonly Uri _url;
1716
private readonly Dictionary<string, string> _headers;
1817
private readonly SemaphoreSlim _reconnectLock = new(1, 1);
19-
private bool _isReconnecting;
20-
private int _reconnectAttempts;
21-
private bool _shouldReconnect = true; // 控制是否应该重连
18+
private int _connectAttempts;
2219
private Task? _healthCheckTask; // 健康检查任务
2320
private const int MaxReconnectDelay = 30000; // 最大重连延迟 30 秒
2421
private const int InitialReconnectDelay = 1000; // 初始重连延迟 1 秒
@@ -63,7 +60,7 @@ public WebsocketClient(
6360
}
6461
catch (Exception ex)
6562
{
66-
_logger?.LogWarning(ex, $"Failed to set header {header.Key}");
63+
_logger?.LogError(ex, $"Failed to set header {header.Key}");
6764
}
6865
}
6966
});
@@ -84,12 +81,12 @@ private async Task StartConnectionAsync()
8481
{
8582
try
8683
{
87-
_logger?.LogInformation($"WebSocket connecting to {_url}");
84+
_logger?.Log($"WebSocket connecting to {_url}");
8885

8986
await Task.Run(() => _client.Start(), _cancellationTokenSource.Token);
9087

9188
// 重置重连计数
92-
_reconnectAttempts = 0;
89+
_connectAttempts = 0;
9390
}
9491
catch (Exception e)
9592
{
@@ -102,15 +99,15 @@ private async Task StartConnectionAsync()
10299
Exception = e,
103100
}
104101
);
105-
106-
// 启动自动重连
107-
_ = TryReconnectAsync();
108102
}
109103
}
110104

111105
private void OnServerConnected(object? sender, EventArgs e)
112106
{
113-
_logger?.LogInformation("WebSocket connected");
107+
_logger?.Log("WebSocket connected");
108+
109+
// 重置重连计数
110+
_connectAttempts = 0;
114111

115112
var connectionInfo = new ConnectionInfo
116113
{
@@ -124,7 +121,7 @@ private void OnServerConnected(object? sender, EventArgs e)
124121

125122
private void OnServerDisconnected(object? sender, EventArgs e)
126123
{
127-
_logger?.LogInformation("WebSocket disconnected");
124+
_logger?.Log("WebSocket disconnected");
128125

129126
OnClosed?.Invoke(
130127
new DisconnectionInfo
@@ -134,107 +131,31 @@ private void OnServerDisconnected(object? sender, EventArgs e)
134131
Timestamp = DateTimeOffset.Now,
135132
}
136133
);
137-
138-
// 只要 _shouldReconnect 为 true,就启动自动重连
139-
if (_shouldReconnect && !_disposed)
140-
{
141-
_ = TryReconnectAsync();
142-
}
143134
}
144135

145-
private async Task TryReconnectAsync()
136+
public async ValueTask ConnectAsync()
146137
{
147-
if (_disposed || !_shouldReconnect)
148-
return;
149-
138+
_logger?.LogDebug(nameof(ConnectAsync) + _url);
150139
// 使用信号量防止并发重连
151-
if (!await _reconnectLock.WaitAsync(0))
152-
return;
153-
154-
try
140+
if (await _reconnectLock.WaitAsync(0))
155141
{
156-
if (_isReconnecting)
157-
return;
158-
159-
_isReconnecting = true;
160-
161-
while (!_disposed && _shouldReconnect)
142+
try
162143
{
163-
_reconnectAttempts++;
164-
165-
// 计算延迟时间(简化的指数退避,1秒到30秒)
166-
var delay = Math.Min(
167-
InitialReconnectDelay << Math.Min(_reconnectAttempts - 1, 5),
168-
MaxReconnectDelay
169-
);
170-
171-
_logger?.LogInformation(
172-
$"Attempting to reconnect (attempt {_reconnectAttempts}) in {delay}ms..."
173-
);
174-
175-
try
176-
{
177-
await Task.Delay(delay, _cancellationTokenSource.Token);
178-
}
179-
catch (OperationCanceledException)
180-
{
181-
// 如果被取消但仍需要重连,继续尝试
182-
if (_shouldReconnect && !_disposed)
183-
{
184-
_logger?.LogInformation(
185-
"Reconnect delay cancelled, but will continue trying..."
186-
);
187-
await Task.Delay(delay); // 使用不带取消令牌的版本
188-
}
189-
else
190-
{
191-
break;
192-
}
193-
}
194-
195-
try
196-
{
197-
if (_client.Connected)
198-
{
199-
_logger?.LogInformation("Already connected, stopping reconnect attempts");
200-
break;
201-
}
202-
203-
_logger?.LogInformation($"Reconnecting to {_url}...");
204-
205-
// 尝试停止现有连接(如果有)
206-
if (_client.Connected)
207-
{
208-
try
209-
{
210-
_client.Stop();
211-
}
212-
catch (Exception stopEx)
213-
{
214-
_logger?.LogDebug(stopEx, "Error stopping client before reconnect");
215-
}
216-
}
217-
218-
await Task.Run(() => _client.Start());
219-
220-
_logger?.LogInformation("Reconnected successfully");
221-
_reconnectAttempts = 0;
222-
break;
223-
}
224-
catch (Exception ex)
144+
_connectAttempts++;
145+
_logger?.Log("Reconnected successfully");
146+
if (await _client.StartWithTimeoutAsync(10))
225147
{
226-
_logger?.LogWarning(ex, $"Reconnect attempt {_reconnectAttempts} failed");
148+
_connectAttempts = 0;
227149
}
228150
}
229-
}
230-
catch (Exception ex)
231-
{
232-
_logger?.LogError(ex, "Error during reconnection process");
233-
}
234-
finally
235-
{
236-
_isReconnecting = false;
237-
_reconnectLock.Release();
151+
catch (Exception ex)
152+
{
153+
_logger?.LogError(ex, $"Reconnect attempt {_connectAttempts} failed");
154+
}
155+
finally
156+
{
157+
_reconnectLock.Release();
158+
}
238159
}
239160
}
240161

@@ -243,36 +164,69 @@ private async Task TryReconnectAsync()
243164
/// </summary>
244165
private async Task RunHealthCheckAsync()
245166
{
246-
while (!_disposed && _shouldReconnect)
167+
while (!_disposed)
247168
{
248169
try
249170
{
250-
await Task.Delay(HealthCheckInterval, _cancellationTokenSource.Token);
251-
}
252-
catch (OperationCanceledException)
253-
{
254-
// 如果被取消但仍需要运行健康检查,继续
255-
if (_shouldReconnect && !_disposed)
171+
// 检查连接状态
172+
if (!_client.Connected)
256173
{
257-
await Task.Delay(HealthCheckInterval);
174+
// 计算延迟时间(简化的指数退避,1秒到30秒)
175+
var delay = Math.Min(
176+
InitialReconnectDelay << Math.Min(_connectAttempts - 1, 5),
177+
MaxReconnectDelay
178+
);
179+
180+
_logger?.Log(
181+
$"Attempting to reconnect (attempt {_connectAttempts}) in {delay}ms..."
182+
);
183+
try
184+
{
185+
await Task.Delay(delay, _cancellationTokenSource.Token);
186+
}
187+
catch (OperationCanceledException)
188+
{
189+
if (_disposed)
190+
break;
191+
}
192+
if (_disposed)
193+
break;
194+
await ConnectAsync();
258195
}
259196
else
260197
{
261-
break;
262-
}
263-
}
198+
// 连接正常,重置重连计数
199+
if (_connectAttempts > 0)
200+
{
201+
_connectAttempts = 0;
202+
}
264203

265-
try
266-
{
267-
// 检查连接状态
268-
if (!_client.Connected && !_isReconnecting)
269-
{
270-
_ = TryReconnectAsync();
204+
// 等待下一次健康检查
205+
try
206+
{
207+
await Task.Delay(HealthCheckInterval, _cancellationTokenSource.Token);
208+
}
209+
catch (OperationCanceledException)
210+
{
211+
if (_disposed)
212+
break;
213+
}
271214
}
272215
}
273216
catch (Exception ex)
274217
{
275218
_logger?.LogError(ex, "Error during health check");
219+
220+
// 发生错误后等待一段时间再继续
221+
try
222+
{
223+
await Task.Delay(HealthCheckInterval, _cancellationTokenSource.Token);
224+
}
225+
catch (OperationCanceledException)
226+
{
227+
if (_disposed)
228+
break;
229+
}
276230
}
277231
}
278232

@@ -321,7 +275,7 @@ private async Task SendAsync(string msg)
321275
{
322276
if (!_client.Connected)
323277
{
324-
_logger?.LogWarning("Cannot send message: WebSocket is not connected");
278+
_logger?.Warn("Cannot send message: WebSocket is not connected");
325279
return;
326280
}
327281

@@ -342,7 +296,6 @@ public void Dispose()
342296
return;
343297

344298
_disposed = true;
345-
_shouldReconnect = false; // 停止重连
346299

347300
try
348301
{
@@ -362,7 +315,7 @@ public void Dispose()
362315
}
363316
catch (Exception ex)
364317
{
365-
_logger?.LogDebug(ex, "Error waiting for health check task to complete");
318+
_logger?.LogError(ex, "Error waiting for health check task to complete");
366319
}
367320
}
368321

0 commit comments

Comments
 (0)