Skip to content

Publish messages out-of-order without waiting the result #1719

@vwxyzh

Description

@vwxyzh

Defect code:

token = _singleWriterMutex.TryWait(options: WaitOptions.NoDelay);
if (!token.Success)
{
   if (PushToBacklog(message, onlyIfExists: !ALWAYS_USE_BACKLOG_IF_CANNOT_GET_SYNC_LOCK))
      return new ValueTask<WriteResult>(WriteResult.Success); // queued counts as success
   ...
}
...
if (!flush.IsCompletedSuccessfully)
{
  ...
  return CompleteWriteAndReleaseLockAsync(token, flush, message, lockTaken);
}

Scenario:
Thread A:

await subscriber.PublishAsync("channel-1", 1);

Thread B:

await Task.WhenAll(subscriber.PublishAsync("channel-2", 2), subscriber.PublishAsync("channel-2", 3));
  1. Thread A try to publish message 1
  2. Thread A takes the lock(_singleWriterMutex) first.
  3. Thread B try to publish message 2
  4. Thread B cannot take the lock, send to backlog.
  5. Thread B create the backlog, and start the background processing.
  6. Thread B returns, since queued counts as success.
  7. Thread A finish the write message 1, release the lock.
  8. Thread B try to publish message 3
  9. Thread B takes the lock.
  10. Thread B finish the write message 3, release the lock.
  11. The backlog takes the lock.
  12. The backlog write message 2.

Then, finally we get following result:
Channel-1: 1
Channel-2: 3, 2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions