tests/multiprocessing.py
changeset 24 5664afa530e5
equal deleted inserted replaced
23:dc2dbe872fc8 24:5664afa530e5
       
     1 #!/usr/bin/env python3
       
     2 '''Multiprocessing test.
       
     3 
       
     4 PgManager is partially safe against process forking.
       
     5 
       
     6 You can create connection credentials (create_conn) in main process, then fork
       
     7 and continue working with pgmanager in children processes. You can call create_conn again
       
     8 in children, but new connection credentials will be accessible only from process
       
     9 where it was created -- no sharing between processes.
       
    10 
       
    11 get_conn and cursor will still work after fork. Connections from parent process will
       
    12 be forgotten, that cannot be used un child process. 
       
    13 
       
    14 Connections cannot be shared between processes, DO NOT:
       
    15  * get_conn, then fork, then put_conn
       
    16  * get_conn, then fork, then use the connection, then .close()
       
    17 
       
    18 Good usage:
       
    19  * create_conn, fork, get_conn, cursor, etc.
       
    20 
       
    21 Basically, you can transfer only information from create_conn(), nothing else.
       
    22 
       
    23 '''
       
    24 
       
    25 
       
    26 import multiprocessing
       
    27 
       
    28 from config import Config
       
    29 from pgtoolkit import pgmanager
       
    30 
       
    31 
       
    32 def sub1(id):
       
    33     with pgm.cursor() as curs:
       
    34         print('[%d] pgconn: %d' % (multiprocessing.current_process().pid, curs.connection.get_backend_pid()))
       
    35         print('[%d] update' % multiprocessing.current_process().pid)
       
    36         curs.execute('''UPDATE test SET name = 'multi-1' WHERE id=%s''', [id])
       
    37         print('[%d] commit' % multiprocessing.current_process().pid)
       
    38         curs.connection.commit()
       
    39 
       
    40 def sub2(id):
       
    41     pgm = pgmanager.get_instance()
       
    42     with pgm.cursor() as curs:
       
    43         print('[%d] pgconn: %d' % (multiprocessing.current_process().pid, curs.connection.get_backend_pid()))
       
    44         print('[%d] update' % multiprocessing.current_process().pid)
       
    45         curs.execute('''UPDATE test SET name = 'multi-2' WHERE id=%s''', [id])
       
    46         print('[%d] commit' % multiprocessing.current_process().pid)
       
    47         curs.connection.commit()
       
    48 
       
    49 
       
    50 cfg = Config('tests.conf')
       
    51 pgm = pgmanager.get_instance()
       
    52 pgm.create_conn(**cfg)
       
    53 
       
    54 with pgm.cursor() as curs:
       
    55     print('[%d] pgconn: %d' % (multiprocessing.current_process().pid, curs.connection.get_backend_pid()))    
       
    56     print('[%d] insert' % multiprocessing.current_process().pid)
       
    57     curs.execute('''INSERT INTO test (name) VALUES ('multi') RETURNING id''')
       
    58     id = curs.fetchone()[0]
       
    59     curs.connection.commit()
       
    60     
       
    61     print('[%d] update' % multiprocessing.current_process().pid)
       
    62     curs.execute('''UPDATE test SET name = 'multi-main' WHERE id=%s''', [id])
       
    63     # not committed
       
    64 
       
    65 p1 = multiprocessing.Process(target=sub1, args=[id])
       
    66 p1.start()
       
    67 p2 = multiprocessing.Process(target=sub2, args=[id])
       
    68 p2.start()
       
    69 
       
    70 with pgm.cursor() as curs:
       
    71     print('[%d] commit' % multiprocessing.current_process().pid)
       
    72     curs.connection.commit()
       
    73 
       
    74 print('join')
       
    75 p1.join()
       
    76 p2.join()
       
    77 
       
    78 print('done')