-
Notifications
You must be signed in to change notification settings - Fork 387
Events monitoring stream does not seems to always include CR or LF character at the end of every messages #434
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
Comments
I'm running into this same issue. The Docker CLI |
The implementation done by @simardst does work but hangs when awaiting for another message before completing the process of the current one. |
I'm also hit by that issue. In my case (WSL) I do not receive any events. When manually applying @simardst fix I'm able to get events but sometime I do not receive a container stop immediatly. I receive this later on when another event comes in. Very annoying. For me it's really hard to understand whats going on because there is a pipestream encapsulated inside a BufferedReadStream encapsualted inside a ChunkReadStream. I will no switch to an own implementation (as I only need the events) internal static async Task MonitorStreamForMessagesAsync<T>(Task<Stream> streamTask, DockerClient client, CancellationToken cancel, IProgress<T> progress)
{
using (var stream = await streamTask)
{
// ReadLineAsync must be cancelled by closing the whole stream.
using (cancel.Register(() => stream.Dispose()))
{
var startObjectCount = 0;
using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
{
try
{
var ch = new char[1];
var sb = new StringBuilder();
while (await reader.ReadAsync(ch, 0, 1).ConfigureAwait(false) == 1)
{
sb.Append(ch[0]);
switch (ch[0])
{
case '}':
{
startObjectCount--;
if (startObjectCount == 0)
{
var prog = client.JsonSerializer.DeserializeObject<T>(sb.ToString());
if (prog == null) continue;
progress.Report(prog);
sb.Clear();
}
break;
}
case '{':
startObjectCount++;
break;
}
}
}
catch (ObjectDisposedException)
{
// The subsequent call to reader.ReadLineAsync() after cancellation
// will fail because we disposed the stream. Just ignore here.
}
}
}
}
} Not fast or beautiful but it works for me at least. |
Here's the implementation that I've been using: using Newtonsoft.Json;
public class EventActor
{
public string Id { get; set; }
public Dictionary<string, string> Attributes { get; set; }
}
public class Event
{
public string Type { get; set; }
public string Action { get; set; }
public EventActor Actor { get; set; }
public int Time { get; set; }
public Int64 TimeNano { get; set; }
}
public class DockerClient
{
public async Task MonitorEvents(
Uri endpoint,
int? since,
int? until,
Dictionary<string, Dictionary<string, bool>> filters,
CancellationToken cancel,
Action<Event> action)
{
var queryParams = new List<string>(3);
if (since != null) { queryParams.Add($"since={since}"); }
if (until != null) { queryParams.Add($"until={until}"); }
if (filters != null) { queryParams.Add($"filters={JsonConvert.SerializeObject(filters)}"); }
var queryString = String.Join("&", queryParams);
var client = new HttpClient();
var uri = new Uri(endpoint, $"events?{queryString}");
var stream = await client.GetStreamAsync(uri);
var serializer = new JsonSerializer();
using (cancel.Register(() => stream.Dispose()))
using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
using (var jsonReader = new JsonTextReader(reader) { SupportMultipleContent = true })
{
try
{
while (jsonReader.Read())
{
var ev = serializer.Deserialize<Event>(jsonReader);
action(ev);
if (cancel.IsCancellationRequested) {
break;
}
}
}
catch (ObjectDisposedException)
{
// Ignore reads on disposed streams
return;
}
}
}
} |
Has anyone looked at how the golang client handles this case? |
Output of
dotnet --info
:What version of Docker.DotNet?:
Docker Version:
Docker Info:
Steps to reproduce the issue:
What actually happened?:
The HTTP request to get the event stream is accepted (200 - OK) and the stream is correctly opened, but there is no CR or LF character to delimit the messages received. Therefore, the stream reader gets stuck (since it is doing ReadLineAsync(...) calls to read messages and parse them)
What did you expect to happen?:
Find a way to extract messages from the event stream without requiring CR or LF charcaters to detect a complete message.
A solution could be to directly parse the stream to extratc JSON objects/messages.
Additional information:
The text was updated successfully, but these errors were encountered: