Skip to content

Commit 107da25

Browse files
authored
Improved Subscription Error Handling (#7127)
1 parent cb28038 commit 107da25

File tree

83 files changed

+3908
-13298
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+3908
-13298
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace CookieCrumble;
2+
3+
internal interface ISnapshotSegment
4+
{
5+
string? Name { get; }
6+
}

src/CookieCrumble/src/CookieCrumble/Snapshot.cs

Lines changed: 98 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public class Snapshot
3838
});
3939
private static readonly JsonSnapshotValueFormatter _defaultFormatter = new();
4040

41-
private readonly List<SnapshotSegment> _segments = [];
41+
private readonly List<ISnapshotSegment> _segments = [];
4242
private readonly string _title;
4343
private readonly string _fileName;
4444
private string _extension;
@@ -159,6 +159,17 @@ public Snapshot Add(
159159
return this;
160160
}
161161

162+
public Snapshot Add(SnapshotValue value)
163+
{
164+
if (value == null)
165+
{
166+
throw new ArgumentNullException(nameof(value));
167+
}
168+
169+
_segments.Add(value);
170+
return this;
171+
}
172+
162173
public Snapshot SetExtension(string extension)
163174
{
164175
if (string.IsNullOrEmpty(extension))
@@ -350,8 +361,17 @@ private void WriteSegments(IBufferWriter<byte> writer)
350361
{
351362
if (_segments.Count == 1)
352363
{
353-
var segment = _segments[0];
354-
segment.Formatter.Format(writer, segment.Value);
364+
switch (_segments[0])
365+
{
366+
case SnapshotSegment segment:
367+
segment.Formatter.Format(writer, segment.Value);
368+
break;
369+
case SnapshotValue value:
370+
writer.Write(value.Value);
371+
break;
372+
default:
373+
throw new NotSupportedException();
374+
}
355375
return;
356376
}
357377

@@ -373,7 +393,17 @@ private void WriteSegments(IBufferWriter<byte> writer)
373393
writer.AppendSeparator();
374394
writer.AppendLine();
375395

376-
segment.Formatter.Format(writer, segment.Value);
396+
switch (segment)
397+
{
398+
case SnapshotSegment s:
399+
s.Formatter.Format(writer, s.Value);
400+
break;
401+
case SnapshotValue v:
402+
writer.Write(v.Value);
403+
break;
404+
default:
405+
throw new NotSupportedException();
406+
}
377407

378408
writer.AppendLine();
379409
writer.AppendSeparator();
@@ -389,18 +419,28 @@ private void WriteMarkdownSegments(IBufferWriter<byte> writer)
389419
{
390420
var segment = _segments[0];
391421

392-
if (segment.Formatter is IMarkdownSnapshotValueFormatter markdownFormatter)
422+
switch (segment)
393423
{
394-
markdownFormatter.FormatMarkdown(writer, segment.Value);
395-
}
396-
else
397-
{
398-
writer.Append("```text");
399-
writer.AppendLine();
400-
segment.Formatter.Format(writer, segment.Value);
401-
writer.AppendLine();
402-
writer.Append("```");
403-
writer.AppendLine();
424+
case SnapshotSegment s:
425+
if (s.Formatter is IMarkdownSnapshotValueFormatter markdownFormatter)
426+
{
427+
markdownFormatter.FormatMarkdown(writer, s.Value);
428+
}
429+
else
430+
{
431+
writer.Append("```text");
432+
writer.AppendLine();
433+
s.Formatter.Format(writer, s.Value);
434+
writer.AppendLine();
435+
writer.Append("```");
436+
writer.AppendLine();
437+
}
438+
break;
439+
case SnapshotValue v:
440+
v.FormatMarkdown(writer);
441+
break;
442+
default:
443+
throw new NotSupportedException();
404444
}
405445
return;
406446
}
@@ -416,19 +456,30 @@ private void WriteMarkdownSegments(IBufferWriter<byte> writer)
416456
writer.AppendLine();
417457
writer.AppendLine();
418458

419-
if (segment.Formatter is IMarkdownSnapshotValueFormatter markdownFormatter)
420-
{
421-
markdownFormatter.FormatMarkdown(writer, segment.Value);
422-
}
423-
else
459+
switch (segment)
424460
{
425-
writer.Append("```text");
426-
writer.AppendLine();
427-
segment.Formatter.Format(writer, segment.Value);
428-
writer.AppendLine();
429-
writer.Append("```");
430-
writer.AppendLine();
461+
case SnapshotSegment s:
462+
if (s.Formatter is IMarkdownSnapshotValueFormatter markdownFormatter)
463+
{
464+
markdownFormatter.FormatMarkdown(writer, s.Value);
465+
}
466+
else
467+
{
468+
writer.Append("```text");
469+
writer.AppendLine();
470+
s.Formatter.Format(writer, s.Value);
471+
writer.AppendLine();
472+
writer.Append("```");
473+
writer.AppendLine();
474+
}
475+
break;
476+
case SnapshotValue v:
477+
v.FormatMarkdown(writer);
478+
break;
479+
default:
480+
throw new NotSupportedException();
431481
}
482+
432483
writer.AppendLine();
433484
}
434485
}
@@ -642,6 +693,7 @@ private static bool IsTheoryTestMethod(MemberInfo? method)
642693
=> method?.GetCustomAttributes(typeof(TheoryAttribute)).Any() ?? false;
643694

644695
private readonly struct SnapshotSegment(string? name, object? value, ISnapshotValueFormatter formatter)
696+
: ISnapshotSegment
645697
{
646698
public string? Name { get; } = name;
647699

@@ -657,3 +709,23 @@ public sealed class DisposableSnapshot(string? postFix = null, string? extension
657709
{
658710
public void Dispose() => Match();
659711
}
712+
713+
public abstract class SnapshotValue : ISnapshotSegment
714+
{
715+
public abstract string? Name { get; }
716+
717+
public abstract ReadOnlySpan<byte> Value { get; }
718+
719+
protected virtual string MarkdownType => "text";
720+
721+
public virtual void FormatMarkdown(IBufferWriter<byte> snapshot)
722+
{
723+
snapshot.Append("```");
724+
snapshot.Append(MarkdownType);
725+
snapshot.AppendLine();
726+
snapshot.Write(Value);
727+
snapshot.AppendLine();
728+
snapshot.Append("```");
729+
snapshot.AppendLine();
730+
}
731+
}

src/CookieCrumble/src/CookieCrumble/TestEnvironment.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Diagnostics;
2+
13
namespace CookieCrumble;
24

35
/// <summary>
@@ -34,4 +36,14 @@ public static bool IsCIEnvironment()
3436
out var result) &&
3537
result;
3638
}
39+
40+
public static CancellationTokenSource CreateCancellationTokenSource(TimeSpan? timeSpan = null)
41+
{
42+
if (Debugger.IsAttached)
43+
{
44+
return new CancellationTokenSource();
45+
}
46+
47+
return new CancellationTokenSource(timeSpan ?? TimeSpan.FromSeconds(10));
48+
}
3749
}

src/HotChocolate/AspNetCore/src/AspNetCore/Serialization/DefaultHttpResponseFormatter.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ public class DefaultHttpResponseFormatter : IHttpResponseFormatter
2727
private readonly FormatInfo _eventStreamFormat;
2828
private readonly FormatInfo _legacyFormat;
2929

30-
3130
/// <summary>
3231
/// Creates a new instance of <see cref="DefaultHttpResponseFormatter" />.
3332
/// </summary>

src/HotChocolate/AspNetCore/src/Transport.Sockets.Client/Protocols/DataMessageObserver.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,13 @@
66

77
namespace HotChocolate.Transport.Sockets.Client.Protocols;
88

9-
internal sealed class DataMessageObserver : IObserver<IOperationMessage>, IDisposable
9+
internal sealed class DataMessageObserver(string id) : IObserver<IOperationMessage>, IDisposable
1010
{
1111
private readonly SemaphoreSlim _semaphore = new(0);
1212
private readonly ConcurrentQueue<IDataMessage> _messages = new();
13-
private readonly string _id;
1413
private Exception? _error;
1514
private bool _disposed;
1615

17-
public DataMessageObserver(string id)
18-
{
19-
_id = id;
20-
}
21-
2216
public async ValueTask<IDataMessage?> TryReadNextAsync(CancellationToken ct)
2317
{
2418
if (_disposed)
@@ -39,7 +33,7 @@ public DataMessageObserver(string id)
3933

4034
public void OnNext(IOperationMessage value)
4135
{
42-
if (value is IDataMessage message && message.Id.EqualsOrdinal(_id))
36+
if (value is IDataMessage message && message.Id.EqualsOrdinal(id))
4337
{
4438
_messages.Enqueue(message);
4539
_semaphore.Release();

src/HotChocolate/AspNetCore/src/Transport.Sockets.Client/Protocols/GraphQLOverWebSocket/GraphQLOverWebSocketProtocolHandler.cs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,10 @@ await context.Socket.CloseAsync(
121121
}
122122
}
123123

124-
private sealed class DataCompletion : IDataCompletion
124+
private sealed class DataCompletion(WebSocket socket, string id) : IDataCompletion
125125
{
126-
private readonly WebSocket _socket;
127-
private readonly string _id;
128126
private bool _completed;
129127

130-
public DataCompletion(WebSocket socket, string id)
131-
{
132-
_socket = socket;
133-
_id = id;
134-
}
135-
136128
public void MarkDataStreamCompleted()
137129
=> _completed = true;
138130

@@ -147,17 +139,17 @@ public void TrySendCompleteMessage()
147139

148140
try
149141
{
150-
if (_socket.IsOpen())
142+
if (socket.IsOpen())
151143
{
152-
await _socket.SendCompleteMessageAsync(_id, cts.Token);
144+
await socket.SendCompleteMessageAsync(id, cts.Token);
153145
}
154146
}
155147
catch
156148
{
157149
// if we cannot send the complete message we will just abort the socket.
158150
try
159151
{
160-
_socket.Abort();
152+
socket.Abort();
161153
}
162154
catch
163155
{

0 commit comments

Comments
 (0)