Skip to content

Process replication slot changes - #4930

Open
DilwoarH wants to merge 66 commits into
mainfrom
process-replication-slot-changes
Open

DilwoarH wants to merge 66 commits into
mainfrom
process-replication-slot-changes

Conversation

@DilwoarH

@DilwoarH DilwoarH commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

** DO NOT MERGE UNTIL #4946 IS MERGED IN FIRST**

What

The application code for processing slot changes for notifications table

Why

This is needed to process WAL logs in the database

Test results

flask shell
import json;
from app.dao.notifications_wal_changes_dao import dao_process_notifications_replication_slot_changes;
result = dao_process_notifications_replication_slot_changes();
print(json.dumps(result, indent=2))

Ran a load test on dev-c - this is the result after 2400 emails.

SELECT
	(SELECT count(*) FROM pg_logical_slot_peek_changes('notify_dashboard_replication_slot', NULL, NULL)) AS still_processing,
    (SELECT SUM(notification_count) FROM ft_service_stats) AS ft_stats_count,
    COUNT(*) AS notif_count,
    (SELECT SUM(notification_count) FROM ft_service_stats where notification_status = 'created') AS ft_created_count,
    COUNT(CASE WHEN notification_status = 'created' THEN 1 END) AS notif_created_count,
    (SELECT SUM(notification_count) FROM ft_service_stats where notification_status = 'sending') AS ft_sending_count,
    COUNT(CASE WHEN notification_status = 'sending' THEN 1 END) AS notif_sending_count,
    (SELECT SUM(notification_count) FROM ft_service_stats where notification_status = 'delivered') AS ft_delivered_count,
    COUNT(CASE WHEN notification_status = 'delivered' THEN 1 END) AS notif_delivered_count,
    (SELECT SUM(notification_count) FROM ft_service_stats where notification_status = 'temporary-failure') AS ft_temp_fail_count,
    COUNT(CASE WHEN notification_status = 'temporary-failure' THEN 1 END) AS notif_temp_fail_count,
    (SELECT SUM(notification_count) FROM ft_service_stats where notification_status = 'permanent-failure') AS ft_perm_fail_count,
    COUNT(CASE WHEN notification_status = 'permanent-failure' THEN 1 END) AS notif_perm_fail_count
FROM
    public.notifications;
still_processing ft_stats_count notif_count ft_created_count notif_created_count ft_sending_count notif_sending_count ft_delivered_count notif_delivered_count ft_temp_fail_count notif_temp_fail_count ft_perm_fail_count notif_perm_fail_count
0 2400 2400 0 0 0 0 1206 1206 234 234 960 960

How it works

605101533-57f970e2-60d7-462a-9fbd-b24d553d6663

@DilwoarH
DilwoarH force-pushed the process-replication-slot-changes branch 6 times, most recently from 6bddcf6 to 2d6790a Compare August 11, 2026 09:53
@DilwoarH
DilwoarH force-pushed the process-replication-slot-changes branch 2 times, most recently from da47acd to 1f988ae Compare August 18, 2026 00:15
@DilwoarH DilwoarH changed the title [WIP] Process replication slot changes Process replication slot changes Aug 18, 2026
@DilwoarH

Copy link
Copy Markdown
Contributor Author

requires #4936 to be merged first

@DilwoarH
DilwoarH force-pushed the process-replication-slot-changes branch from 1f988ae to 1d032b9 Compare August 18, 2026 00:29
Comment thread app/dao/fact_service_stats_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py Outdated
@DilwoarH
DilwoarH force-pushed the process-replication-slot-changes branch 3 times, most recently from 09efa7c to 29d32f3 Compare September 8, 2026 12:09
Comment thread app/celery/scheduled_tasks.py Outdated
Comment thread app/dao/fact_service_stats_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py
Comment thread app/dao/notifications_wal_changes_dao.py
Comment thread app/dao/notifications_wal_changes_dao.py Outdated
Comment thread app/dao/notifications_wal_changes_dao.py
@DilwoarH
DilwoarH force-pushed the process-replication-slot-changes branch from 29d32f3 to a1c7a1f Compare September 25, 2026 09:43
This makes it more stricter on what is being passed in
We no longer need this as format 1 is redundant
…ogic

This also drops the user of FactServiceStats.

This was done as we want to have FactNotificationStatusLive to be a drop in
replacement for FactNotificationStatus.
This will help us understand how test keys are used and potentially display this information back to user.
The file path is already exposed as part of the log
sessions should not be shared across processes
@DilwoarH
DilwoarH force-pushed the process-replication-slot-changes branch from 7bf769e to 3bfc05b Compare October 22, 2026 10:57
@DilwoarH
DilwoarH force-pushed the process-replication-slot-changes branch from 3bfc05b to 526ef99 Compare October 22, 2026 11:09
@DilwoarH

Copy link
Copy Markdown
Contributor Author

@risicle

The following changes have been made:

  • reorder batch_last_lsn check so that it happens before any return
  • removed additional checks before acquiring lock
  • removed additional advancing slot logic and let main flow handle processing
  • removed celery schedule so that it doesn't start processing WAL entries (we will use an alternative method)

@DilwoarH
DilwoarH dismissed spatel033’s stale review October 22, 2026 14:18

Rob is reviewing

if not payload:
continue

if isinstance(payload, str):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😕 what happens if it's not?

If this is just to please mypy, we could do

assert isinstance(payload, str) # type narrowing

which is something we've done elsewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated with new logic



def apply_notification_status_live_change(dimensions: NotificationStatusLiveDimensions, change_count: int) -> None:
_update_notification_status_live_count(dimensions, change_count)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function needed anymore?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@DilwoarH

DilwoarH commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor Author

@risicle

You can test this locally using:

flask shell
import json;
from app.dao.notifications_wal_changes_dao import dao_process_notifications_replication_slot_changes;
result = dao_process_notifications_replication_slot_changes();
print(json.dumps(result, indent=2));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants