PgManager: Add partial support for multiprocessing.
#!/usr/bin/env python3
'''Multiprocessing test.
PgManager is partially safe against process forking.
You can create connection credentials (create_conn) in main process, then fork
and continue working with pgmanager in children processes. You can call create_conn again
in children, but new connection credentials will be accessible only from process
where it was created -- no sharing between processes.
get_conn and cursor will still work after fork. Connections from parent process will
be forgotten, that cannot be used un child process.
Connections cannot be shared between processes, DO NOT:
* get_conn, then fork, then put_conn
* get_conn, then fork, then use the connection, then .close()
Good usage:
* create_conn, fork, get_conn, cursor, etc.
Basically, you can transfer only information from create_conn(), nothing else.
'''
import multiprocessing
from config import Config
from pgtoolkit import pgmanager
def sub1(id):
with pgm.cursor() as curs:
print('[%d] pgconn: %d' % (multiprocessing.current_process().pid, curs.connection.get_backend_pid()))
print('[%d] update' % multiprocessing.current_process().pid)
curs.execute('''UPDATE test SET name = 'multi-1' WHERE id=%s''', [id])
print('[%d] commit' % multiprocessing.current_process().pid)
curs.connection.commit()
def sub2(id):
pgm = pgmanager.get_instance()
with pgm.cursor() as curs:
print('[%d] pgconn: %d' % (multiprocessing.current_process().pid, curs.connection.get_backend_pid()))
print('[%d] update' % multiprocessing.current_process().pid)
curs.execute('''UPDATE test SET name = 'multi-2' WHERE id=%s''', [id])
print('[%d] commit' % multiprocessing.current_process().pid)
curs.connection.commit()
cfg = Config('tests.conf')
pgm = pgmanager.get_instance()
pgm.create_conn(**cfg)
with pgm.cursor() as curs:
print('[%d] pgconn: %d' % (multiprocessing.current_process().pid, curs.connection.get_backend_pid()))
print('[%d] insert' % multiprocessing.current_process().pid)
curs.execute('''INSERT INTO test (name) VALUES ('multi') RETURNING id''')
id = curs.fetchone()[0]
curs.connection.commit()
print('[%d] update' % multiprocessing.current_process().pid)
curs.execute('''UPDATE test SET name = 'multi-main' WHERE id=%s''', [id])
# not committed
p1 = multiprocessing.Process(target=sub1, args=[id])
p1.start()
p2 = multiprocessing.Process(target=sub2, args=[id])
p2.start()
with pgm.cursor() as curs:
print('[%d] commit' % multiprocessing.current_process().pid)
curs.connection.commit()
print('join')
p1.join()
p2.join()
print('done')