Re: Background worker with Listen

From: Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>
To: Jinhua Luo <luajit(dot)io(at)gmail(dot)com>
Cc: "Ihnat Peter | TSS Group a(dot)s(dot)" <Ihnat(at)tssgroup(dot)sk>, "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: Re: Background worker with Listen
Date: 2016-04-26 09:21:53
Message-ID: CAFj8pRAbfYdhwkgw81Xf8Qv89gk+KcZAfUOSvHe1MVRNfRkb2Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

2016-04-26 11:17 GMT+02:00 Jinhua Luo <luajit(dot)io(at)gmail(dot)com>:

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

there must be some overhead from using client API on server side.

Regards

Pavel

>
> 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;
> >
> > }
>
>
> --
> Sent via pgsql-general mailing list (pgsql-general(at)postgresql(dot)org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-general
>

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Wetzel, Juergen (Juergen) 2016-04-26 12:45:21 Re: Intemittendly get "server process (PID 5884) exited with exit code 3"
Previous Message Jinhua Luo 2016-04-26 09:17:40 Re: Background worker with Listen