From a42474f7129d5031065b51af56a5acf6b34b8c22 Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Wed, 6 Dec 2023 17:04:35 +0000 Subject: [PATCH] Get newly suspended users each time we refresh any users (#4949) --- .../src/services/userIndex/candid/idl.js | 1 + .../src/services/userIndex/candid/types.d.ts | 1 + .../services/userIndex/userIndex.client.ts | 23 ++++++++++++------- .../openchat-agent/src/utils/userCache.ts | 21 ++++++++++++++++- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/frontend/openchat-agent/src/services/userIndex/candid/idl.js b/frontend/openchat-agent/src/services/userIndex/candid/idl.js index f381bb8f6b..2ef513c758 100644 --- a/frontend/openchat-agent/src/services/userIndex/candid/idl.js +++ b/frontend/openchat-agent/src/services/userIndex/candid/idl.js @@ -292,6 +292,7 @@ export const idlFactory = ({ IDL }) => { 'updated_since' : TimestampMillis, }) ), + 'users_suspended_since' : IDL.Opt(TimestampMillis), }); const UsersV2Response = IDL.Variant({ 'Success' : IDL.Record({ diff --git a/frontend/openchat-agent/src/services/userIndex/candid/types.d.ts b/frontend/openchat-agent/src/services/userIndex/candid/types.d.ts index 29ea4ac10f..bd94e95aac 100644 --- a/frontend/openchat-agent/src/services/userIndex/candid/types.d.ts +++ b/frontend/openchat-agent/src/services/userIndex/candid/types.d.ts @@ -1538,6 +1538,7 @@ export interface UsersV2Args { 'user_groups' : Array< { 'users' : Array, 'updated_since' : TimestampMillis } >, + 'users_suspended_since' : [] | [TimestampMillis], } export type UsersV2Response = { 'Success' : { 'timestamp' : TimestampMillis, 'users' : Array } diff --git a/frontend/openchat-agent/src/services/userIndex/userIndex.client.ts b/frontend/openchat-agent/src/services/userIndex/userIndex.client.ts index c1207870d5..25741d3055 100644 --- a/frontend/openchat-agent/src/services/userIndex/userIndex.client.ts +++ b/frontend/openchat-agent/src/services/userIndex/userIndex.client.ts @@ -40,8 +40,10 @@ import { apiOptional, apiToken } from "../common/chatMappers"; import type { AgentConfig } from "../../config"; import { getCachedUsers, + getSuspendedUsersSyncedUpTo, setCachedUsers, setDisplayNameInCache, + setSuspendedUsersSyncedUpTo, setUserDiamondStatusInCache, setUsernameInCache, } from "../../utils/userCache"; @@ -121,12 +123,13 @@ export class UserIndexClient extends CandidService { const allUsers = users.userGroups.flatMap((g) => g.users); const fromCache = await getCachedUsers(allUsers); + const suspendedUsersSyncedTo = await getSuspendedUsersSyncedUpTo(); // We throw away all of the updatedSince values passed in and instead use the values from the cache, this // ensures the cache is always correct and doesn't miss any updates const args = this.buildGetUsersArgs(allUsers, fromCache, allowStale); - const response = await this.getUsersFromBackend(users); + const response = await this.getUsersFromBackend(users, suspendedUsersSyncedTo); const requestedFromServer = new Set([...args.userGroups.flatMap((g) => g.users)]); @@ -142,23 +145,27 @@ export class UserIndexClient extends CandidService { console.error("Failed to save users to the cache", err), ); + if (mergedResponse.serverTimestamp !== undefined) { + setSuspendedUsersSyncedUpTo(mergedResponse.serverTimestamp).catch((err) => + console.error("Failed to set 'suspended users synced up to' in the cache", err), + ); + } + return mergedResponse; } - private getUsersFromBackend(users: UsersArgs): Promise { + private getUsersFromBackend( + users: UsersArgs, + suspendedUsersSyncedUpTo: bigint | undefined, + ): Promise { const userGroups = users.userGroups.filter((g) => g.users.length > 0); - if (userGroups.length === 0) { - return Promise.resolve({ - serverTimestamp: undefined, - users: [], - }); - } const args = { user_groups: userGroups.map(({ users, updatedSince }) => ({ users: users.map((u) => Principal.fromText(u)), updated_since: updatedSince, })), + users_suspended_since: apiOptional(identity, suspendedUsersSyncedUpTo), }; return this.handleQueryResponse( () => this.userIndexService.users_v2(args), diff --git a/frontend/openchat-agent/src/utils/userCache.ts b/frontend/openchat-agent/src/utils/userCache.ts index 0668114ade..2931c7c118 100644 --- a/frontend/openchat-agent/src/utils/userCache.ts +++ b/frontend/openchat-agent/src/utils/userCache.ts @@ -1,7 +1,7 @@ import { openDB, type DBSchema, type IDBPDatabase } from "idb"; import type { DiamondMembershipStatus, UserSummary } from "openchat-shared"; -const CACHE_VERSION = 4; +const CACHE_VERSION = 5; let db: UserDatabase | undefined; @@ -12,6 +12,11 @@ export interface UserSchema extends DBSchema { key: string; value: UserSummary; }; + + suspendedUsersSyncedUpTo: { + key: "value"; + value: bigint; + }; } export function lazyOpenUserCache(): UserDatabase { @@ -27,7 +32,11 @@ function openUserCache(): UserDatabase { if (db.objectStoreNames.contains("users")) { db.deleteObjectStore("users"); } + if (db.objectStoreNames.contains("suspendedUsersSyncedUpTo")) { + db.deleteObjectStore("suspendedUsersSyncedUpTo"); + } db.createObjectStore("users"); + db.createObjectStore("suspendedUsersSyncedUpTo"); }, }); } @@ -109,3 +118,13 @@ export async function setUserDiamondStatusInCache( } await tx.done; } + +export async function getSuspendedUsersSyncedUpTo(): Promise { + const resolvedDb = await lazyOpenUserCache(); + return await resolvedDb.get("suspendedUsersSyncedUpTo", "value"); +} + +export async function setSuspendedUsersSyncedUpTo(value: bigint): Promise { + const resolvedDb = await lazyOpenUserCache(); + await resolvedDb.put("suspendedUsersSyncedUpTo", value, "value"); +}