[英]Postgres pg_notify does not notify when a table gets updated from a stored procedure that is called via the Timescaledb Action's job scheduler
I have two tables in my Postgres DB.我的Postgres DB 中有两个表。 Table A is where all the data is stored.
表 A 是存储所有数据的地方。 A stored procedure (X) does some aggregation of the data in Table A and has insert/update statement for Table B. Using the Timescaledb Actions's job scheduler, every 1 hour X is called and table B gets updated or a new data is inserted in it.
存储过程 (X) 对表 A 中的数据进行了一些聚合,并对表 B 具有插入/更新语句。使用Timescaledb Actions 的作业调度程序,每 1 小时调用一次 X 并更新表 B 或插入新数据它。 I have another trigger (T) that is triggered every time Table B gets updated or when a new record is inserted in it, the trigger simply
PERFORM pg_notify('channel',payload)
.我有另一个触发器(T),每次更新表 B 或在其中插入新记录时都会触发,触发器只是
PERFORM pg_notify('channel',payload)
。 Python backend receives the notification by executing Listen
command from the psycopg2
. Python 后端通过执行来自
psycopg2
的Listen
命令接收通知。
When I try to INSERT/UPDATE
with random data in Table B, Python receives the Notification.当我尝试使用表 B 中的随机数据
INSERT/UPDATE
时,Python 会收到通知。 But Python does not receives any notification when Stored Procedure update/inserts in Table B. The trigger (T) is not triggered when Table B gets updated or inserted from the Stored Procedure X.但是当存储过程在表 B 中更新/插入时,Python 没有收到任何通知。当从存储过程 X 更新或插入表 B 时,不会触发触发器 (T)。
I have read the Notify documentation.我已阅读通知文档。 But I am sure I might have missed something important.
但我确信我可能错过了一些重要的事情。 If anyone could help me with this, I will be grateful.
如果有人可以帮助我,我将不胜感激。
--TRIGGER FUNCTION TO NOTIFY
CREATE FUNCTION newDataTableB() RETURNS trigger AS $$
DECLARE
rec RECORD;
payload TEXT;
BEGIN
rec := new;
payload := json_build_object(TG_OP, rec.id);
-- Notify the channel
PERFORM pg_notify('db_notifications', payload);
RETURN rec;
END;
$$ LANGUAGE plpgsql;
-- TRIGGER ON TABLE B
CREATE TRIGGER newDataTableB_tr AFTER INSERT OR UPDATE ON tableB FOR EACH ROW EXECUTE PROCEDURE newDataTableB();
--Stored Procedure
CREATE OR REPLACE PROCEDURE insertIntoTableB(job_id int, config jsonb) LANGUAGE PLPGSQL AS $$
DECLARE
rec_findSpeed record;
cur_findSpeed refcursor;
BEGIN
--materialized view to find average of Speed stored in table A that is group by trip_id
REFRESH MATERIALIZED VIEW findSpeed;
open cur_findSpeed for SELECT * from findSpeed;
loop
fetch cur_findSpeed into rec_findSpeed;
exit when not found;
IF EXISTS (SELECT * FROM tableB WHERE trip_id = rec_findSpeed.trip_id) THEN
update tableB set averageSpeed=rec_findSpeed.averageSpeed, min_time = rec_findSpeed.min_time where trip_id = rec_findSpeed.trip_id;
ELSE
INSERT into tableB(averageSpeed, min_time, trip_id)
values(rec_findSpeed.averageSpeed, rec_findSpeed.min_time, rec_findSpeed.trip_id)
END IF;
end loop;
close cur_findSpeed;
END;
$$;
SELECT add_job('insertIntoTableB','1h');
-- MATERIALIZED VIEW
CREATE MATERIALIZED VIEW findSpeed AS
SELECT AVG(speed) as averageSpeed, trip_id, min(time) as min_time
FROM tableA
GROUP BY trip_id
WITH DATA;
Python code as requested. Python 代码按要求。 The Python backend requires to execute some other queries after it receives the notification.
Python后端收到通知后需要执行一些其他的查询。 I followed the psycopg2 .
我跟着psycopg2 。 I didn't understand everything as I am new to psycopg2.
我不了解所有内容,因为我是 psycopg2 的新手。 Please, tell me how should I proceed with this.
请告诉我我该怎么做。
def wait(conn):
while True:
state = conn.poll()
if state == psycopg2.extensions.POLL_OK:
break
elif state == psycopg2.extensions.POLL_WRITE:
select.select([], [conn.fileno()], [])
elif state == psycopg2.extensions.POLL_READ:
select.select([conn.fileno()], [], [])
else:
raise psycopg2.OperationalError("poll() returned %s" % state)
@app.route('/startListening', methods=['POST'])
def listen():
conn = psycopg2.connect(dsn, async_=True)
wait(conn)
cur = conn.cursor()
cur.execute("LISTEN db_notifications")
wait(conn)
print("Listening on db_notifications")
while True:
conn.poll()
while conn.notifies:
notify = conn.notifies.pop()
print(notify)
handle_event(notify, conn)
def handle_event(noti,connec):
data_from_notifications = noti.payload
print(data_from_notifications)
#some data processing
#next cursor and query
acur = connec.cursor()
acur.execute('')
wait(connec)
The problem is the Timescaldb's action job scheduler.问题是 Timescaldb 的动作作业调度程序。 I moved to pgAgent job scheduler, and everything was working exactly how it's supposed to be.
我搬到了 pgAgent 作业调度程序,一切都按照它应该的方式工作。
I think the problem is in the python code.我认为问题出在 python 代码中。 Could you try this, without the server context of your example?
如果没有示例的服务器上下文,您可以试试这个吗?
conn = psycopg2.connect(dsn, async_=True)
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cur = conn.cursor()
cur.execute("LISTEN db_notifications")
r, w, e = select.select([conn.fileno()], [], [], timeout)
conn.poll()
for n in conn.notifies:
print(n.channel)
print(n)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.