/// <summary> /// Listen database on selected channels /// </summary> /// <param name="stoppingToken">Cancellation</param> /// <returns></returns> public async Task ListenDb(CancellationToken stoppingToken) { await ParallelHelper.Run(() => { Log.Info($"Listening started for DB: {_dbName}"); while (!stoppingToken.IsCancellationRequested) { try { using (PgSqlDbConnect connect = new PgSqlDbConnect(_connectionString)) { connect.Open(); connect.UnderlyingConnection.Notification += OnNotification; connect.Execute($"LISTEN {PgSqlDbConnect.CHANNEL_GENESIS_REQUEST};"); connect.Execute($"LISTEN {PgSqlDbConnect.CHANNEL_GENESIS_DELETE};"); connect.Execute($"LISTEN {PgSqlDbConnect.CHANNEL_BACKUP_REQUEST};"); while (!stoppingToken.IsCancellationRequested && connect.UnderlyingConnection.State == ConnectionState.Open) { connect.UnderlyingConnection.Wait(100); } } } catch (Exception e) { Log.Error(e); Thread.Sleep(1000); } } }); }
/// <summary> /// Event on DB notification on listened channels occurs /// </summary> /// <param name="sender">Sender of event</param> /// <param name="args">Event arguments</param> private void OnNotification(object sender, NpgsqlNotificationEventArgs args) { try { switch (args.Channel) { case PgSqlDbConnect.CHANNEL_GENESIS_REQUEST: { if (string.IsNullOrEmpty(args.Payload)) { throw new ArgumentException("Payload is empty"); } string filePath = Path.Combine(_config["GenesisOutputDir"], args.Payload + ".sql"); FileHelper.DirectoryEnsure(filePath); string exePath = _config["PgDumpPath"]; string argsText = $"{_config["GenesisArgs"]} --file=\"{filePath}\" {_dbName}"; Log.Info($"RUN {exePath} {argsText}"); Process pgsql = Process.Start(exePath, argsText); pgsql?.WaitForExit(); using (PgSqlDbConnect connect2 = new PgSqlDbConnect(_connectionString)) { connect2.Open(); connect2.Execute($"SELECT pg_notify('{PgSqlDbConnect.CHANNEL_GENESIS_RESPOND}', '{filePath}'::TEXT);"); } break; } case PgSqlDbConnect.CHANNEL_GENESIS_DELETE: { File.Delete(args.Payload); break; } case PgSqlDbConnect.CHANNEL_BACKUP_REQUEST: { string exePath = _config["PgDumpAllPath"]; string filePath = Path.Combine(_config["BackupOutputDir"], _config["BackupFilePrefix"] + DateTimeHelper.Now.ToString(DateTimeHelper.FORMAT_FULL).Replace(".", "_").Replace(":", "_").Replace(" ", "_") + ".pgbak"); string argsText = $"{_config["BackupArgs"]} --file=\"{filePath}\""; Log.Info($"RUN {exePath} {argsText}"); Process pgsql = Process.Start(exePath, argsText); pgsql?.WaitForExit(); break; } } } catch (Exception ex) { Log.Error(ex, $"{args.Channel} [{args.Payload}]"); } }