Thread: Connect from background worker thread to database

Connect from background worker thread to database

From
Олексій Васильєв
Date:
Hello everyone.

I am new to writing extensions to PostgreSQL. And I am not familiar with the C language (My professional languages: Ruby, Golang, Java). But still want to write an extension for PostgreSQL.

After articles of Michael Paquier about  background workers in PostgreSQL, I realized what I can create what I always want - web interface for this database. This interface will provide some info about database (like in couchbase: http://docs.couchbase.com/couchbase-manual-2.0/images/web-console-cluster-overview.png) and can be used as REST API.

Right now this server should work as JSON API and I will build on top of this API web interface on some JS framework. My initiative right now is working as web server just with some hello string. But I don't understand how should I connect to database from threads in web server. All source you can find here: https://github.com/le0pard/pg_web

This is part where I try to connect to database: https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L92-L132, but SPI functions give error in log (it is commented):

2013-11-24 02:57:43 UTC ERROR:  stack depth limit exceeded

2013-11-24 02:57:43 UTC HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.

2013-11-24 02:57:43 UTC CONTEXT:  SQL statement "SELECT COUNT(*) FROM pg_class;"

Because I doing something in wrong way. I will appreciate for any help: where I doing wrong, link to the article how to do it, just a tip, pull request - anything. Google search and PostgreSQL sources reading  so far helped me to this point.


Thanks in advance, Alexey




Re: Connect from background worker thread to database

From
Andres Freund
Date:
Hi,

On 2013-11-24 16:27:06 +0400, Олексій Васильєв wrote:
> This is part where I try to connect to database:  https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L92-L132
,but SPI functions give error in log (it is commented):
 
> 
> 2013-11-24 02:57:43 UTC ERROR:  stack depth limit exceeded
> 2013-11-24 02:57:43 UTC HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after
ensuringthe platform's stack depth limit is adequate.
 
> 2013-11-24 02:57:43 UTC CONTEXT:  SQL statement "SELECT COUNT(*) FROM pg_class;"
> 
> Because I doing something in wrong way. I will appreciate for any help: where I doing wrong, link to the article how
todo it, just a tip, pull request - anything. Google search and PostgreSQL sources reading  so far helped me to this
point.

At the very least you're calling InitPostgres() instead of
BackgroundWorkerInitializeConnection() which you have commented out. And
the latter should only be called once in every worker.

Greetings,

Andres Freund



Re[2]: [HACKERS] Connect from background worker thread to database

From
Олексій Васильєв
Date:
If I remove comment from BackgroundWorkerInitializeConnection https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L179 and comment InitPostgres https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L98, I have the same errors in log:

2013-11-24 13:35:24 UTC ERROR:  stack depth limit exceeded

2013-11-24 13:35:24 UTC HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.

2013-11-24 13:35:24 UTC CONTEXT:  SQL statement "SELECT COUNT(*) FROM pg_class;"

2013-11-24 13:35:25 UTC LOG:  worker process: pg_web (PID 1957) exited with exit code 1

2013-11-24 13:35:26 UTC LOG:  starting background worker process "pg_web"

2013-11-24 13:35:26 UTC INFO:  Start web server on port 8080
If I change InitPostgres to BackgroundWorkerInitializeConnection and leave BackgroundWorkerInitializeConnection in bgw_main, I will have this error:

2013-11-24 13:39:58 UTC ERROR:  invalid processing mode in background worker

2013-11-24 13:39:58 UTC LOG:  worker process: pg_web (PID 2719) exited with exit code 1

2013-11-24 13:39:59 UTC LOG:  starting background worker process "pg_web"
Воскресенье, 24 ноября 2013, 14:06 +01:00 от Andres Freund <andres@anarazel.de>:

Hi,

On 2013-11-24 16:27:06 +0400, Олексій Васильєв wrote:
> This is part where I try to connect to database:  https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L92-L132 , but SPI functions give error in log (it is commented):
>
> 2013-11-24 02:57:43 UTC ERROR:  stack depth limit exceeded
> 2013-11-24 02:57:43 UTC HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
> 2013-11-24 02:57:43 UTC CONTEXT:  SQL statement "SELECT COUNT(*) FROM pg_class;"
>
> Because I doing something in wrong way. I will appreciate for any help: where I doing wrong, link to the article how to do it, just a tip, pull request - anything. Google search and PostgreSQL sources reading  so far helped me to this point.

At the very least you're calling InitPostgres() instead of
BackgroundWorkerInitializeConnection() which you have commented out. And
the latter should only be called once in every worker.

Greetings,

Andres Freund


Re[2]: [HACKERS] Connect from background worker thread to database

From
Alexey Vasiliev
Date:
Воскресенье, 24 ноября 2013, 14:06 +01:00 от Andres Freund <andres@anarazel.de>:
Hi,

On 2013-11-24 16:27:06 +0400, Олексій Васильєв wrote:
> This is part where I try to connect to database:  https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L92-L132 , but SPI functions give error in log (it is commented):
>
> 2013-11-24 02:57:43 UTC ERROR:  stack depth limit exceeded
> 2013-11-24 02:57:43 UTC HINT:  Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platform's stack depth limit is adequate.
> 2013-11-24 02:57:43 UTC CONTEXT:  SQL statement "SELECT COUNT(*) FROM pg_class;"
>
> Because I doing something in wrong way. I will appreciate for any help: where I doing wrong, link to the article how to do it, just a tip, pull request - anything. Google search and PostgreSQL sources reading  so far helped me to this point.

At the very least you're calling InitPostgres() instead of
BackgroundWorkerInitializeConnection() which you have commented out. And
the latter should only be called once in every worker.

Greetings,

Andres Freund

Fixed by using PQconnectdb from "libpq-fe.h". Thanks.


--
Alexey Vasiliev

Re: Re[2]: [HACKERS] Connect from background worker thread to database

From
Michael Paquier
Date:
On Mon, Nov 25, 2013 at 2:10 AM, Alexey Vasiliev <leopard_ne@inbox.ru> wrote:
> Воскресенье, 24 ноября 2013, 14:06 +01:00 от Andres Freund
> <andres@anarazel.de>:
>
> Hi,
>
>
> On 2013-11-24 16:27:06 +0400, Олексій Васильєв wrote:
>> This is part where I try to connect to database:
>> https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L92-L132 , but
>> SPI functions give error in log (it is commented):
>>
>> 2013-11-24 02:57:43 UTC ERROR:  stack depth limit exceeded
>> 2013-11-24 02:57:43 UTC HINT:  Increase the configuration parameter
>> "max_stack_depth" (currently 2048kB), after ensuring the platform's stack
>> depth limit is adequate.
>> 2013-11-24 02:57:43 UTC CONTEXT:  SQL statement "SELECT COUNT(*) FROM
>> pg_class;"
>>
>> Because I doing something in wrong way. I will appreciate for any help:
>> where I doing wrong, link to the article how to do it, just a tip, pull
>> request - anything. Google search and PostgreSQL sources reading  so far
>> helped me to this point.
>
> At the very least you're calling InitPostgres() instead of
> BackgroundWorkerInitializeConnection() which you have commented out. And
> the latter should only be called once in every worker.
>
> Greetings,
>
> Andres Freund
>
>
> Fixed by using PQconnectdb from "libpq-fe.h". Thanks.
You should not need an extra PQconnectdb to connect to a database
using a background worker for your case as far as I understood. By
using that you are requiring a connection to database without using
the internal infrastructure in place, meaning that your bgworker is
not connected to the database server from the inside but from the
outside, like a normal client would do. Aren't to trying to have a
background worker connected to a database when it is initialized with
BgWorkerStart_PostmasterStart? Bgworkers using this start-up mode are
not eligible to initialize database connections. Please use either
BgWorkerStart_ConsistentState or BgWorkerStart_RecoveryFinished and
BackgroundWorkerInitializeConnection will allow a connection to
database without any extra work.
--
Michael



Re[2]: [HACKERS] Re[2]: [HACKERS] Connect from background worker thread to database

From
Alexey Vasiliev
Date:
Понедельник, 25 ноября 2013, 8:31 +09:00 от Michael Paquier <michael.paquier@gmail.com>:
On Mon, Nov 25, 2013 at 2:10 AM, Alexey Vasiliev <leopard_ne@inbox.ru> wrote:
> Воскресенье, 24 ноября 2013, 14:06 +01:00 от Andres Freund
> <andres@anarazel.de>:
>
> Hi,
>
>
> On 2013-11-24 16:27:06 +0400, Олексій Васильєв wrote:
>> This is part where I try to connect to database:
>> https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L92-L132 , but
>> SPI functions give error in log (it is commented):
>>
>> 2013-11-24 02:57:43 UTC ERROR: stack depth limit exceeded
>> 2013-11-24 02:57:43 UTC HINT: Increase the configuration parameter
>> "max_stack_depth" (currently 2048kB), after ensuring the platform's stack
>> depth limit is adequate.
>> 2013-11-24 02:57:43 UTC CONTEXT: SQL statement "SELECT COUNT(*) FROM
>> pg_class;"
>>
>> Because I doing something in wrong way. I will appreciate for any help:
>> where I doing wrong, link to the article how to do it, just a tip, pull
>> request - anything. Google search and PostgreSQL sources reading so far
>> helped me to this point.
>
> At the very least you're calling InitPostgres() instead of
> BackgroundWorkerInitializeConnection() which you have commented out. And
> the latter should only be called once in every worker.
>
> Greetings,
>
> Andres Freund
>
>
> Fixed by using PQconnectdb from "libpq-fe.h". Thanks.
You should not need an extra PQconnectdb to connect to a database
using a background worker for your case as far as I understood. By
using that you are requiring a connection to database without using
the internal infrastructure in place, meaning that your bgworker is
not connected to the database server from the inside but from the
outside, like a normal client would do. Aren't to trying to have a
background worker connected to a database when it is initialized with
BgWorkerStart_PostmasterStart? Bgworkers using this start-up mode are
not eligible to initialize database connections. Please use either
BgWorkerStart_ConsistentState or BgWorkerStart_RecoveryFinished and
BackgroundWorkerInitializeConnection will allow a connection to
database without any extra work.
--
Michael
Thanks, I just try this. This work if I working with database in loop inside bgw_main function. But if I create threads inside bgw_main and try to connect to database - I have errors "stack depth limit exceeded" . The code:

https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L195 - connect to database
https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L100-L131 - "http_event_handler" function execute in threads, because it handle http requests. And this code not work. BTW, I need connect to database depend from request url, so execute BackgroundWorkerInitializeConnection at the beginning not enough.

Thanks again.

--
Alexey Vasiliev

Re: Re[2]: [HACKERS] Connect from background worker thread to database

From
Michael Paquier
Date:
On Mon, Nov 25, 2013 at 1:02 PM, Alexey Vasiliev <leopard_ne@inbox.ru> wrote:
> Thanks, I just try this. This work if I working with database in loop inside
> bgw_main function. But if I create threads inside bgw_main and try to
> connect to database - I have errors "stack depth limit exceeded" . The code:
>
> https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L195 - connect to
> database
> https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L100-L131 -
> "http_event_handler" function execute in threads, because it handle http
> requests. And this code not work. BTW, I need connect to database depend
> from request url, so execute BackgroundWorkerInitializeConnection at the
> beginning not enough.
There is a design problem with your application when trying to create
threads with mg_start in order to grab events. Note that I am not
familiar with mongoose, but with bgworkers you cannot simply create
new threads that would be able to connect to server concurrently. A
model that would be more suited with bgworkers would be something
like:
- Handle event messages by for example opening a port or monitoring
the events on a single bgworker launched by bgw_main, with for example
a message queue model (possible with 9.3). Connection to database
would be done with a single connection, managed within the loop of
bgw_main.
- Create a new bgworker dynamically each time a new event comes in
(possible only with 9.4~). The top work would be done by a central
bgworker initialized with server, which would treat events and kick
new slave workers when necessary.

Regards,
-- 
Michael



Re[2]: [HACKERS] Re[2]: [HACKERS] Connect from background worker thread to database

From
Alexey Vasiliev
Date:
Понедельник, 25 ноября 2013, 13:31 +09:00 от Michael Paquier <michael.paquier@gmail.com>:
On Mon, Nov 25, 2013 at 1:02 PM, Alexey Vasiliev <leopard_ne@inbox.ru> wrote:
> Thanks, I just try this. This work if I working with database in loop inside
> bgw_main function. But if I create threads inside bgw_main and try to
> connect to database - I have errors "stack depth limit exceeded" . The code:
>
> https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L195 - connect to
> database
> https://github.com/le0pard/pg_web/blob/master/src/pg_web.c#L100-L131 -
> "http_event_handler" function execute in threads, because it handle http
> requests. And this code not work. BTW, I need connect to database depend
> from request url, so execute BackgroundWorkerInitializeConnection at the
> beginning not enough.
There is a design problem with your application when trying to create
threads with mg_start in order to grab events. Note that I am not
familiar with mongoose, but with bgworkers you cannot simply create
new threads that would be able to connect to server concurrently. A
model that would be more suited with bgworkers would be something
like:
- Handle event messages by for example opening a port or monitoring
the events on a single bgworker launched by bgw_main, with for example
a message queue model (possible with 9.3). Connection to database
would be done with a single connection, managed within the loop of
bgw_main.
- Create a new bgworker dynamically each time a new event comes in
(possible only with 9.4~). The top work would be done by a central
bgworker initialized with server, which would treat events and kick
new slave workers when necessary.

Regards,
--
Michael


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Thanks. I will look how to do this in the best way by your suggestions.

--
Alexey Vasiliev