From 004041dcc562e60cc54b6233e8318120a8f96723 Mon Sep 17 00:00:00 2001 From: vadimkibana Date: Wed, 5 Oct 2022 14:07:31 +0200 Subject: [PATCH 1/5] update short url access fields on resolution by slug --- .../short_urls/short_url_client.test.ts | 54 ++++++++++++++++++- .../short_urls/short_url_client.ts | 14 +++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/plugins/share/server/url_service/short_urls/short_url_client.test.ts b/src/plugins/share/server/url_service/short_urls/short_url_client.test.ts index fe6365d498628..4578f63ca1a6e 100644 --- a/src/plugins/share/server/url_service/short_urls/short_url_client.test.ts +++ b/src/plugins/share/server/url_service/short_urls/short_url_client.test.ts @@ -44,6 +44,15 @@ const setup = () => { }; }; +const tick = (ms: number = 1) => new Promise((r) => setTimeout(r, ms)); + +const until = async (check: () => Promise, pollInterval: number = 1) => { + do { + if (await check()) return; + await tick(pollInterval); + } while (true); +}; + describe('ServerShortUrlClient', () => { describe('.create()', () => { test('can create a short URL', async () => { @@ -72,6 +81,20 @@ describe('ServerShortUrlClient', () => { }, }); }); + + test('initializes "accessDate" and "accessCount" fields on URL creation', async () => { + const { client, locator } = setup(); + const { data } = await client.create({ + locator, + slug: 'lala', + params: { + url: '/app/test#foo/bar/baz', + }, + }); + + expect(data.accessDate).toBeGreaterThan(Date.now() - 1000000); + expect(data.accessCount).toBe(0); + }); }); describe('.resolve()', () => { @@ -85,7 +108,7 @@ describe('ServerShortUrlClient', () => { }); const shortUrl2 = await client.resolve(shortUrl1.data.slug); - expect(shortUrl2.data).toMatchObject(shortUrl1.data); + expect(shortUrl2.data).toStrictEqual(shortUrl1.data); }); test('can create short URL with custom slug', async () => { @@ -128,6 +151,33 @@ describe('ServerShortUrlClient', () => { }) ).rejects.toThrowError(new UrlServiceError(`Slug "lala" already exists.`, 'SLUG_EXISTS')); }); + + test('updates "accessCount" and "accessDate" on URL resolution by slug', async () => { + const { client, locator } = setup(); + const shortUrl1 = await client.create({ + locator, + params: { + url: '/app/test#foo/bar/baz', + }, + }); + + expect(shortUrl1.data.accessDate).toBeGreaterThan(Date.now() - 1000000); + expect(shortUrl1.data.accessCount).toBe(0); + + await client.resolve(shortUrl1.data.slug); + await until(async () => (await client.get(shortUrl1.data.id)).data.accessCount === 1); + const shortUrl2 = await client.get(shortUrl1.data.id); + + expect(shortUrl2.data.accessDate).toBeGreaterThanOrEqual(shortUrl1.data.accessDate); + expect(shortUrl2.data.accessCount).toBe(1); + + await client.resolve(shortUrl1.data.slug); + await until(async () => (await client.get(shortUrl1.data.id)).data.accessCount === 2); + const shortUrl3 = await client.get(shortUrl1.data.id); + + expect(shortUrl3.data.accessDate).toBeGreaterThanOrEqual(shortUrl2.data.accessDate); + expect(shortUrl3.data.accessCount).toBe(2); + }); }); describe('.get()', () => { @@ -141,7 +191,7 @@ describe('ServerShortUrlClient', () => { }); const shortUrl2 = await client.get(shortUrl1.data.id); - expect(shortUrl2.data).toMatchObject(shortUrl1.data); + expect(shortUrl2.data).toStrictEqual(shortUrl1.data); }); test('throws when fetching non-existing short URL', async () => { diff --git a/src/plugins/share/server/url_service/short_urls/short_url_client.ts b/src/plugins/share/server/url_service/short_urls/short_url_client.ts index cecc4c3127135..dd4f35c6b0f77 100644 --- a/src/plugins/share/server/url_service/short_urls/short_url_client.ts +++ b/src/plugins/share/server/url_service/short_urls/short_url_client.ts @@ -143,12 +143,26 @@ export class ServerShortUrlClient implements IShortUrlClient { const { storage } = this.dependencies; const record = await storage.getBySlug(slug); const data = this.injectReferences(record); + this.updateAccessFields(record); return { data, }; } + /** + * Access field updates are executed in the background as we don't need to + * wait for them and confirm that they were successful. + */ + protected updateAccessFields(record: ShortUrlRecord) { + const { storage } = this.dependencies; + storage.update(record.data.id, { + accessDate: Date.now(), + accessCount: record.data.accessCount + 1, + }) + .catch(() => {}); // We are not interested if it succeeds or not. + } + public async delete(id: string): Promise { const { storage } = this.dependencies; await storage.delete(id); From 066893e76d2aaa7902c3a15943cd1e57c4ee8714 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:16:49 +0000 Subject: [PATCH 2/5] [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' --- .../server/url_service/short_urls/short_url_client.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/share/server/url_service/short_urls/short_url_client.ts b/src/plugins/share/server/url_service/short_urls/short_url_client.ts index dd4f35c6b0f77..f130216b53aa6 100644 --- a/src/plugins/share/server/url_service/short_urls/short_url_client.ts +++ b/src/plugins/share/server/url_service/short_urls/short_url_client.ts @@ -156,10 +156,11 @@ export class ServerShortUrlClient implements IShortUrlClient { */ protected updateAccessFields(record: ShortUrlRecord) { const { storage } = this.dependencies; - storage.update(record.data.id, { - accessDate: Date.now(), - accessCount: record.data.accessCount + 1, - }) + storage + .update(record.data.id, { + accessDate: Date.now(), + accessCount: record.data.accessCount + 1, + }) .catch(() => {}); // We are not interested if it succeeds or not. } From 8d78df6eb2043af113d397e24d964d4fb382cb5f Mon Sep 17 00:00:00 2001 From: vadimkibana Date: Wed, 5 Oct 2022 14:28:54 +0200 Subject: [PATCH 3/5] improve field update method --- .../share/server/url_service/short_urls/short_url_client.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/share/server/url_service/short_urls/short_url_client.ts b/src/plugins/share/server/url_service/short_urls/short_url_client.ts index dd4f35c6b0f77..4af5711cf37a9 100644 --- a/src/plugins/share/server/url_service/short_urls/short_url_client.ts +++ b/src/plugins/share/server/url_service/short_urls/short_url_client.ts @@ -156,9 +156,11 @@ export class ServerShortUrlClient implements IShortUrlClient { */ protected updateAccessFields(record: ShortUrlRecord) { const { storage } = this.dependencies; - storage.update(record.data.id, { + const { id, ...attributes } = record.data; + storage.update(id, { + ...attributes, accessDate: Date.now(), - accessCount: record.data.accessCount + 1, + accessCount: (attributes.accessCount || 0) + 1, }) .catch(() => {}); // We are not interested if it succeeds or not. } From 8455b87d3f9af6fe0b4ddb3a34fefebde055b7c2 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 5 Oct 2022 12:36:36 +0000 Subject: [PATCH 4/5] [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' --- .../url_service/short_urls/short_url_client.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/plugins/share/server/url_service/short_urls/short_url_client.ts b/src/plugins/share/server/url_service/short_urls/short_url_client.ts index 601eb2448ed09..096b2610b916a 100644 --- a/src/plugins/share/server/url_service/short_urls/short_url_client.ts +++ b/src/plugins/share/server/url_service/short_urls/short_url_client.ts @@ -154,14 +154,15 @@ export class ServerShortUrlClient implements IShortUrlClient { * Access field updates are executed in the background as we don't need to * wait for them and confirm that they were successful. */ - protected updateAccessFields(record: ShortUrlRecord) { + protected updateAccessFields(record: ShortUrlRecord) { const { storage } = this.dependencies; const { id, ...attributes } = record.data; - storage.update(id, { - ...attributes, - accessDate: Date.now(), - accessCount: (attributes.accessCount || 0) + 1, - }) + storage + .update(id, { + ...attributes, + accessDate: Date.now(), + accessCount: (attributes.accessCount || 0) + 1, + }) .catch(() => {}); // We are not interested if it succeeds or not. } From 0444e70dbd3162cae302ef0daeb2d1ac43144bdd Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 5 Oct 2022 13:16:27 +0000 Subject: [PATCH 5/5] [CI] Auto-commit changed files from 'node scripts/build_plugin_list_docs' --- docs/developer/plugin-list.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 407261c6f1d7e..4853d859b371a 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -71,7 +71,7 @@ as uiSettings within the code. |{kib-repo}blob/{branch}/src/plugins/data_views/README.mdx[dataViews] |The data views API provides a consistent method of structuring and formatting documents -and field lists across the various Kibana apps. Its typically used in conjunction with +and field lists across the various Kibana apps. It's typically used in conjunction with for composing queries.