diff --git a/packages/kvs-client/src/__tests__/client.test.ts b/packages/kvs-client/src/__tests__/client.test.ts index f7820d6493..862abd6f53 100644 --- a/packages/kvs-client/src/__tests__/client.test.ts +++ b/packages/kvs-client/src/__tests__/client.test.ts @@ -139,7 +139,11 @@ describe('KeyValueClient', () => { describe('listKeys', () => { it('should send GET request to namespace endpoint', async () => { - const testData = { key1: 'value1', key2: 'value2' } + const testData = { + count: 2, + keys: ['key1', 'key2'], + namespace: 'test-ns' + } fetchMock.mockResponseOnce(JSON.stringify(testData), { status: 200, headers: { 'Content-Type': 'application/json' } diff --git a/packages/kvs-client/src/client.ts b/packages/kvs-client/src/client.ts index 618e100a02..f209ab689b 100644 --- a/packages/kvs-client/src/client.ts +++ b/packages/kvs-client/src/client.ts @@ -14,7 +14,7 @@ // import { concatLink } from '@hcengineering/core' import { PlatformError } from '@hcengineering/platform' -import { KeyValueClient } from './types' +import { KeyValueClient, ListResult } from './types' /** * Get a KeyValueClient instance @@ -92,12 +92,12 @@ class KeyValueClientImpl implements KeyValueClient { }) } - async listKeys(prefix?: string): Promise | null> { + async listKeys (prefix?: string): Promise { let url = this.buildUrl() if (prefix !== undefined) { url += `?prefix=${encodeURIComponent(prefix)}` } - return await this.sendRequest>(url, { + return await this.sendRequest(url, { method: 'GET', errorMessage: 'Failed to list keys' }) diff --git a/packages/kvs-client/src/types.ts b/packages/kvs-client/src/types.ts index 5f2d1d413a..8ddf0a817f 100644 --- a/packages/kvs-client/src/types.ts +++ b/packages/kvs-client/src/types.ts @@ -13,6 +13,12 @@ // limitations under the License. // +export interface ListResult { + keys: string[] + count: number + namespace: string +} + /** * Client for interacting with the key-value store API * @public @@ -45,5 +51,5 @@ export interface KeyValueClient { * @param prefix - Optional prefix to filter keys by * @returns Promise that resolves to an object with keys and their values */ - listKeys: (prefix?: string) => Promise | null> + listKeys: (prefix?: string) => Promise } diff --git a/services/calendar/pod-calendar/src/kvsUtils.ts b/services/calendar/pod-calendar/src/kvsUtils.ts index 18b9efa14d..6f9302d51c 100644 --- a/services/calendar/pod-calendar/src/kvsUtils.ts +++ b/services/calendar/pod-calendar/src/kvsUtils.ts @@ -92,7 +92,7 @@ export async function removeUserByEmail (user: User, email: GoogleEmail): Promis export async function cleanUserByEmail (): Promise { const client = getKvsClient() - const keys = await client.listKeys(`${CALENDAR_INTEGRATION}:users:`) + const keys = await client.listKeys(`${CALENDAR_INTEGRATION}:users:`) if (keys == null) return for (const key in keys) { await client.deleteKey(key) diff --git a/services/calendar/pod-calendar/src/watch.ts b/services/calendar/pod-calendar/src/watch.ts index 87f6d1544e..a8d2effacd 100644 --- a/services/calendar/pod-calendar/src/watch.ts +++ b/services/calendar/pod-calendar/src/watch.ts @@ -33,11 +33,11 @@ export class WatchClient { return watchClient } - private async getWatches (): Promise> { + private async getWatches (): Promise { const client = getKvsClient() const key = `${CALENDAR_INTEGRATION}:watch:${this.user.email}` - const watches = await client.listKeys(key) - return watches ?? {} + const watches = await client.listKeys(key) + return watches?.keys ?? [] } private async setToken (token: Credentials): Promise { @@ -65,7 +65,7 @@ export class WatchClient { if (active.length === 0) { const watches = await this.getWatches() const client = getKvsClient() - for (const key in watches) { + for (const key of watches) { await client.deleteKey(key) } } @@ -187,7 +187,15 @@ export class WatchController { private async getUserWatches (email: GoogleEmail): Promise> { const client = getKvsClient() const key = `${CALENDAR_INTEGRATION}:watch:${email}` - return (await client.listKeys(key)) ?? {} + const keys = (await client.listKeys(key))?.keys ?? [] + const res: Record = {} + for (const key of keys) { + const watch = await client.getValue(key) + if (watch != null) { + res[key] = watch + } + } + return res } async unsubscribe (user: Token): Promise { @@ -227,10 +235,11 @@ export class WatchController { const expired = Date.now() + 24 * 60 * 60 * 1000 const client = getKvsClient() const key = `${CALENDAR_INTEGRATION}:watch:` - const watches = (await client.listKeys(key)) ?? {} + const watches = await client.listKeys(key) const toRefresh: Watch[] = [] - for (const key in watches) { - const watch = watches[key] + for (const key of watches?.keys ?? []) { + const watch = await client.getValue(key) + if (watch == null) continue if (watch.expired < expired) { toRefresh.push(watch) }