#!/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 tests.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')
