Re: Background worker with Listen

From: Jinhua Luo <luajit(dot)io(at)gmail(dot)com>
To: "Ihnat Peter | TSS Group a(dot)s(dot)" <Ihnat(at)tssgroup(dot)sk>
Cc: "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: Re: Background worker with Listen
Date: 2016-04-26 09:17:40
Message-ID: CAAc9rOyJ55Kx+9QAnUa0NMgOMPPJS0Q4GU9=Fh=7qBhaujxR+Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Why not use libpq in worker? i.e. your worker works just like a pure PG client.

In my project, I uses worker in this way and it works well. I do not
use any backend API to access the database.

2016-04-21 15:51 GMT+08:00 Ihnat Peter | TSS Group a.s. <Ihnat(at)tssgroup(dot)sk>:
> 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;
>
> }

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Pavel Stehule 2016-04-26 09:21:53 Re: Background worker with Listen
Previous Message Peter Kardoš 2016-04-26 08:56:45 Re: Background worker with Listen