/// <summary> /// Replicates binlog events from the server /// </summary> /// <param name="handleEvent">Client callback function</param> /// <returns>Task completed when last event is read in non-blocking mode</returns> public async Task ReplicateAsync(Func <IBinlogEvent, Task> handleEvent, CancellationToken cancellationToken = default) { await ConnectAsync(cancellationToken); await AdjustStartingPosition(cancellationToken); await SetMasterHeartbeat(cancellationToken); await SetMasterBinlogChecksum(cancellationToken); await _databaseProvider.DumpBinlogAsync(_channel, _options, cancellationToken); await ReadEventStreamAsync(handleEvent, cancellationToken); }
/// <summary> /// Replicates binlog events from the server /// </summary> /// <param name="handleEvent">Client callback function</param> /// <returns>Task completed when last event is read in non-blocking mode</returns> public async Task ReplicateAsync(Func <IBinlogEvent, Task> handleEvent) { await ConnectAsync(); await AdjustStartingPosition(); await SetMasterHeartbeat(); await SetMasterBinlogChecksum(); await _databaseProvider.DumpBinlogAsync(_channel, _options); await ReadEventStreamAsync(handleEvent); }
/// <summary> /// Replicates binlog events from the server /// </summary> /// <param name="cancellationToken">Cancellation token</param> /// <returns>Task completed when last event is read in non-blocking mode</returns> public async IAsyncEnumerable <IBinlogEvent> Replicate([EnumeratorCancellation] CancellationToken cancellationToken = default) { await ConnectAsync(cancellationToken); // Clear on reconnect _gtid = null; _transaction = false; await AdjustStartingPosition(cancellationToken); await SetMasterHeartbeat(cancellationToken); await SetMasterBinlogChecksum(cancellationToken); await _databaseProvider.DumpBinlogAsync(_channel, _options, cancellationToken); var eventStreamReader = new EventStreamReader(_databaseProvider.Deserializer); var channel = new EventStreamChannel(eventStreamReader, _channel.Stream); var timeout = _options.HeartbeatInterval.Add(TimeSpan.FromMilliseconds(TimeoutConstants.Delta)); await foreach (var packet in channel.ReadPacketAsync(timeout, cancellationToken).WithCancellation(cancellationToken)) { if (packet is IBinlogEvent binlogEvent) { // We stop replication if client code throws an exception // As a derived database may end up in an inconsistent state. yield return(binlogEvent); // Commit replication state if there is no exception. UpdateGtidPosition(binlogEvent); UpdateBinlogPosition(binlogEvent); } else if (packet is EndOfFilePacket && !_options.Blocking) { yield break; } else if (packet is ErrorPacket error) { throw new InvalidOperationException($"Event stream error. {error.ToString()}"); } else { throw new InvalidOperationException($"Event stream unexpected error."); } } }