Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        /// <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.");
                }
            }
        }