|
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') |