Skip to content

Commit cf1f46b

Browse files
committed
tests: Add tests exercising Lua consumers
In particular, check that events can be consumed, and that the last delivered event is redelivered if the connection is GC'd without being closed, or closed with `consume_current_event=False`. Signed-off-by: Matt Wozniski <mwozniski@bloomberg.net>
1 parent 7073b4d commit cf1f46b

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

tests/test_lua_consumer.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import pytest
2+
3+
from comdb2 import dbapi2
4+
from comdb2 import factories
5+
6+
MONITOR_PROCEDURE = """
7+
local function main()
8+
db:column_type('int', 1)
9+
db:column_name('id', 1)
10+
11+
db:column_type('text', 2)
12+
db:column_name('old_message', 2)
13+
14+
db:column_type('text', 3)
15+
db:column_name('new_message', 3)
16+
17+
local consumer = db:consumer()
18+
while true do
19+
local change = consumer:get()
20+
local row = {id=nil, old_message=nil, new_message=nil}
21+
if change.new ~= nil then
22+
row.id = change.new.id
23+
row.new_message = change.new.message
24+
end
25+
if change.old ~= nil then
26+
row.id = change.old.id
27+
row.old_message = change.old.message
28+
end
29+
30+
consumer:emit(row)
31+
consumer:consume()
32+
end
33+
end
34+
"""
35+
36+
37+
@pytest.fixture(autouse=True)
38+
def create_consumer():
39+
conn = dbapi2.Connection("mattdb", "dev", autocommit=True)
40+
cursor = conn.cursor()
41+
42+
# Drop existing consumer/procedure/table (just in case)
43+
try:
44+
cursor.execute("DROP LUA CONSUMER monitor")
45+
except dbapi2.Error:
46+
pass
47+
48+
try:
49+
cursor.execute("DROP PROCEDURE monitor VERSION 'test'")
50+
except dbapi2.Error:
51+
pass
52+
53+
cursor.execute("DROP TABLE IF EXISTS monitored")
54+
55+
# (Re)create table/procedure/consumer
56+
cursor.execute("CREATE TABLE monitored(id int, message vutf8)")
57+
cursor.execute(
58+
"CREATE PROCEDURE monitor VERSION 'test' { " + MONITOR_PROCEDURE + "}"
59+
)
60+
cursor.execute(
61+
"CREATE LUA CONSUMER monitor"
62+
" ON (TABLE monitored FOR INSERT AND UPDATE AND DELETE)"
63+
)
64+
65+
yield
66+
67+
cursor.execute("DROP LUA CONSUMER monitor")
68+
cursor.execute("DROP PROCEDURE monitor VERSION 'test'")
69+
cursor.execute("DROP TABLE monitored")
70+
71+
72+
def test_redelivery_after_gc_without_close():
73+
# GIVEN
74+
conn = dbapi2.Connection("mattdb", "dev", autocommit=True)
75+
conn.row_factory = factories.dict_row_factory
76+
cursor = conn.cursor()
77+
cursor.execute("insert into monitored(id, message) values (1, 'hi')")
78+
cursor.execute("insert into monitored(id, message) values (2, 'hey')")
79+
cursor.execute("insert into monitored(id, message) values (3, 'bye')")
80+
81+
cursor.execute("exec procedure monitor()")
82+
assert cursor.fetchone() == {"id": 1, "old_message": None, "new_message": "hi"}
83+
assert cursor.fetchone() == {"id": 2, "old_message": None, "new_message": "hey"}
84+
cursor = None
85+
conn = None
86+
87+
conn = dbapi2.Connection("mattdb", "dev", autocommit=True)
88+
conn.row_factory = factories.dict_row_factory
89+
cursor = conn.cursor()
90+
91+
# WHEN
92+
cursor.execute("exec procedure monitor()")
93+
94+
# THEN
95+
assert cursor.fetchone() == {"id": 2, "old_message": None, "new_message": "hey"}
96+
97+
98+
def test_redelivery_after_close_without_consume():
99+
# GIVEN
100+
conn = dbapi2.Connection("mattdb", "dev", autocommit=True)
101+
conn.row_factory = factories.dict_row_factory
102+
cursor = conn.cursor()
103+
cursor.execute("insert into monitored(id, message) values (1, 'hi')")
104+
cursor.execute("insert into monitored(id, message) values (2, 'hey')")
105+
cursor.execute("insert into monitored(id, message) values (3, 'bye')")
106+
107+
cursor.execute("exec procedure monitor()")
108+
assert cursor.fetchone() == {"id": 1, "old_message": None, "new_message": "hi"}
109+
assert cursor.fetchone() == {"id": 2, "old_message": None, "new_message": "hey"}
110+
cursor = None
111+
conn.close(ack_current_event=False)
112+
conn = None
113+
114+
conn = dbapi2.Connection("mattdb", "dev", autocommit=True)
115+
conn.row_factory = factories.dict_row_factory
116+
cursor = conn.cursor()
117+
118+
# WHEN
119+
cursor.execute("exec procedure monitor()")
120+
121+
# THEN
122+
assert cursor.fetchone() == {"id": 2, "old_message": None, "new_message": "hey"}
123+
124+
125+
def test_no_redelivery_after_default_close():
126+
# GIVEN
127+
conn = dbapi2.Connection("mattdb", "dev", autocommit=True)
128+
conn.row_factory = factories.dict_row_factory
129+
cursor = conn.cursor()
130+
cursor.execute("insert into monitored(id, message) values (1, 'hi')")
131+
cursor.execute("insert into monitored(id, message) values (2, 'hey')")
132+
cursor.execute("insert into monitored(id, message) values (3, 'bye')")
133+
134+
cursor.execute("exec procedure monitor()")
135+
assert cursor.fetchone() == {"id": 1, "old_message": None, "new_message": "hi"}
136+
assert cursor.fetchone() == {"id": 2, "old_message": None, "new_message": "hey"}
137+
cursor = None
138+
conn.close()
139+
conn = None
140+
141+
conn = dbapi2.Connection("mattdb", "dev", autocommit=True)
142+
conn.row_factory = factories.dict_row_factory
143+
cursor = conn.cursor()
144+
145+
# WHEN
146+
cursor.execute("exec procedure monitor()")
147+
148+
# THEN
149+
assert cursor.fetchone() == {"id": 3, "old_message": None, "new_message": "bye"}

0 commit comments

Comments
 (0)