Background worker with Listen

From: Ihnat Peter | TSS Group a(dot)s(dot) <Ihnat(at)TSSGROUP(dot)sk>
To: "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: Background worker with Listen
Date: 2016-04-21 07:51:40
Message-ID: 653F38FD5CD7424981050380095AE47A10C81AA3@SRVEXCHANGE.TSSGROUP.local
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

I am trying to create background worker which listens to notifications and do some work after receiving one.
I got 2 problems:

- Worker is receiving notifications from every channel not only the registered channel (in my case "foo")

- Notifications are not logged in the server log - I cannot store the payloads for further work
Any help is welcomed.

Here is the code:

PG_MODULE_MAGIC;

void _PG_init(void);
void _PG_fini(void);

static volatile sig_atomic_t got_sigterm = false;
static volatile sig_atomic_t got_sigusr1 = false;
static char *notify_database = NULL;
static emit_log_hook_type prev_log_hook = NULL;

static void
bgw_sigterm(SIGNAL_ARGS)
{
int save_errno = errno;
got_sigterm = true;
if (MyProc)
SetLatch(&MyProc->procLatch);
errno = save_errno;
}

static void
bgw_sigusr1(SIGNAL_ARGS)
{
int save_errno = errno;
got_sigusr1 = true;
if (MyProc)
SetLatch(&MyProc->procLatch);
errno = save_errno;
}

static void
notify_main(Datum main_arg)
{
pqsignal(SIGTERM, bgw_sigterm);
pqsignal(SIGUSR1, bgw_sigusr1);

BackgroundWorkerUnblockSignals();
BackgroundWorkerInitializeConnection(notify_database, NULL);
EnableNotifyInterrupt();

pgstat_report_activity(STATE_RUNNING, "background_worker");
StartTransactionCommand();
Async_Listen("foo");
CommitTransactionCommand();
pgstat_report_activity(STATE_IDLE, NULL);

while (!got_sigterm)
{
int rc;

rc = WaitLatch(&MyProc->procLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, 10000L);
ResetLatch(&MyProc->procLatch);

if (rc & WL_POSTMASTER_DEATH)
proc_exit(1);

if (got_sigusr1)
{
got_sigusr1 = false;
elog(INFO, " background_worker: notification received");
// DO SOME WORK WITH STORED NOTIFICATIONS
}

}

elog(LOG, "background_worker: finished");
proc_exit(0);
}

static void
store_notification(ErrorData *edata)
{
// HERE STORE THE NOTIFICATION FROM SERVER LOG

if (prev_log_hook)
(*prev_log_hook) (edata);
}

void
_PG_init(void)
{
BackgroundWorker worker;
DefineCustomStringVariable("postgres", NULL, NULL, &notify_database,
"postgres",
PGC_POSTMASTER, 0, NULL, NULL, NULL);

MemSet(&worker, 0, sizeof(BackgroundWorker));
snprintf(worker.bgw_name, BGW_MAXLEN, "background_worker");
worker.bgw_flags = BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION;
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
worker.bgw_main = notify_main;
worker.bgw_restart_time = 10;
worker.bgw_main_arg = (Datum) 0;
worker.bgw_notify_pid = 0;
RegisterBackgroundWorker(&worker);

prev_log_hook = emit_log_hook;
emit_log_hook = store_notification;
}

void
_PG_fini(void)
{
emit_log_hook = prev_log_hook;
}

Responses

Browse pgsql-general by date

  From Date Subject
Next Message martin.kamp.jensen 2016-04-21 08:05:01 Invalid data read from synchronously replicated hot standby
Previous Message Karsten Hilbert 2016-04-21 07:11:23 Re: Add relcreated (timestamp) column to pg_class catalog to record the time an object was created