Skip to content

Commit 3eca676

Browse files
fix: sync raven push user tokens (#2075)
* fix(notification): use delete_doc for unsubscribing notification * feat(notification): add SyncDataButton component * fix(notification): group user tokens into chunks for push notifications
1 parent dd78852 commit 3eca676

3 files changed

Lines changed: 46 additions & 12 deletions

File tree

frontend/src/pages/settings/PushNotifications.tsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,7 @@ const PushNotifications = () => {
215215
<RegisterSiteButton mutate={mutate} ravenSettings={ravenSettings} />}
216216

217217
{isRavenCloud && ravenSettings?.push_notification_service === "Raven"
218-
&& ravenSettings?.push_notification_server_url && ravenSettings?.vapid_public_key && <Button
219-
onClick={() => call.post('raven.api.notification.sync_user_tokens_to_raven_cloud').then(() => {
220-
toast.success('Data syncing to Raven Cloud...')
221-
})}
222-
type='button'
223-
variant='soft'
224-
className='not-cal'>
225-
Sync Data to Raven Cloud
226-
</Button>}
218+
&& ravenSettings?.push_notification_server_url && ravenSettings?.vapid_public_key && <SyncDataButton />}
227219

228220
{!isRavenCloud && <Button
229221
asChild
@@ -270,4 +262,25 @@ const RegisterSiteButton = ({ mutate, ravenSettings }: { mutate: VoidFunction, r
270262

271263
}
272264

265+
const SyncDataButton = () => {
266+
const { call, loading } = useFrappePostCall('raven.api.notification.sync_user_tokens_to_raven_cloud')
267+
268+
const syncData = () => {
269+
toast.promise(call({}), {
270+
loading: 'Syncing data to Raven Cloud...',
271+
success: 'Data synced to Raven Cloud.',
272+
error: (error) => 'Failed to sync data to Raven Cloud. ' + (getErrorMessage(error))
273+
})
274+
}
275+
276+
return <Button
277+
onClick={syncData}
278+
disabled={loading}
279+
variant='soft'
280+
type='button'
281+
className='not-cal'>
282+
{loading ? "Syncing Data to Raven Cloud..." : "Sync Data to Raven Cloud"}
283+
</Button>
284+
}
285+
273286
export const Component = PushNotifications

raven/api/notification.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ def unsubscribe(fcm_token: str) -> None:
104104
Remove the FCM token from the database
105105
"""
106106

107-
frappe.db.delete("Raven Push Token", {"fcm_token": fcm_token, "user": frappe.session.user})
107+
# Check if the FCM token exists
108+
token_name = frappe.db.exists(
109+
"Raven Push Token", {"fcm_token": fcm_token, "user": frappe.session.user}
110+
)
111+
if not token_name:
112+
frappe.throw(_("FCM token not found"))
113+
114+
# Delete the FCM token from the database using delete_doc to ensure that on_trash method gets called to delete the token from RC/FCP.
115+
frappe.delete_doc("Raven Push Token", token_name)
108116

109117
return "Unsubscribed"

raven/raven_cloud_notifications.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,21 @@ def sync_users_tokens_to_raven_cloud():
6565
raven_settings = frappe.get_single("Raven Settings")
6666
tokens = frappe.db.get_all("Raven Push Token", fields=["user", "fcm_token"], order_by="user")
6767

68-
# We need to divide these into chunks of 10
69-
chunks = [tokens[i : i + 10] for i in range(0, len(tokens), 10)]
68+
# Group tokens by user to ensure all tokens for a user are in the same chunk
69+
user_tokens = {}
70+
for token in tokens:
71+
user_tokens.setdefault(token["user"], []).append(token)
72+
73+
# Build chunks where all tokens for a user stay together
74+
chunks = []
75+
current_chunk = []
76+
for user, user_token_list in user_tokens.items():
77+
if len(current_chunk) + len(user_token_list) > 10 and current_chunk:
78+
chunks.append(current_chunk)
79+
current_chunk = []
80+
current_chunk.extend(user_token_list)
81+
if current_chunk:
82+
chunks.append(current_chunk)
7083

7184
for chunk in chunks:
7285
client = FrappeClient(

0 commit comments

Comments
 (0)