From 42bd106d11d80b8ba9a0020b3397e35d87449f5a Mon Sep 17 00:00:00 2001 From: panchongyang Date: Mon, 20 Feb 2023 14:38:05 +0800 Subject: [PATCH 1/2] chore: Style code --- src/EventRecorder.ts | 45 +++++++++++------------ src/FeatureProbe.ts | 68 +++++++++++++++++++---------------- src/autoReportEvents.ts | 25 ++++++------- test/autoReportEvents.test.ts | 13 +++---- 4 files changed, 80 insertions(+), 71 deletions(-) diff --git a/src/EventRecorder.ts b/src/EventRecorder.ts index 7c30500..c3d38c0 100644 --- a/src/EventRecorder.ts +++ b/src/EventRecorder.ts @@ -11,19 +11,6 @@ export class EventRecorder { private timer: NodeJS.Timer; private readonly dispatch: Promise; - set flushInterval(value: number) { - clearInterval(this.timer); - this.timer = setInterval(() => this.flush(), value); - } - - get accessQueue(): IAccessEvent[] { - return this.sendAccessQueue; - } - - get eventQueue(): (AccessEvent | CustomEvent | ClickEvent | PageViewEvent)[] { - return this.sendEventQueue; - } - constructor( clientSdkKey: string, eventsUrl: string, @@ -39,6 +26,19 @@ export class EventRecorder { this.dispatch = this.startDispatch(); } + set flushInterval(value: number) { + clearInterval(this.timer); + this.timer = setInterval(() => this.flush(), value); + } + + get accessQueue(): IAccessEvent[] { + return this.sendAccessQueue; + } + + get eventQueue(): (AccessEvent | CustomEvent | ClickEvent | PageViewEvent)[] { + return this.sendEventQueue; + } + public recordAccessEvent(accessEvent: IAccessEvent): void { if (this.closed) { console.warn("Trying to push access record to a closed EventProcessor, omitted"); @@ -158,27 +158,28 @@ class AsyncBlockingQueue { this.promises = []; } - private add() { - this.promises.push(new Promise(resolve => { - this.resolvers.push(resolve); - })); - } - - enqueue(t: T) { + public enqueue(t: T) { if (!this.resolvers.length) { this.add(); } this.resolvers.shift()?.(t); } - dequeue(): Promise | undefined { + public dequeue(): Promise | undefined { if (!this.promises.length) { this.add(); } return this.promises.shift(); } - isEmpty() { + public isEmpty() { return !this.promises.length; } + + private add() { + this.promises.push(new Promise(resolve => { + this.resolvers.push(resolve); + })); + } + } diff --git a/src/FeatureProbe.ts b/src/FeatureProbe.ts index 7d51ae1..3c0d0e8 100644 --- a/src/FeatureProbe.ts +++ b/src/FeatureProbe.ts @@ -23,6 +23,9 @@ const STATUS = { ERROR: "error", }; +const REFRESHINTERVAL = 1000; +const TIMEOUTINTERVAL = 10000; + /** * You can obtainan a client of FeatureProbe, * which provides access to all of the SDK's functionality. @@ -54,8 +57,8 @@ class FeatureProbe extends TinyEmitter { realtimePath, clientSdkKey, user, - refreshInterval = 1000, - timeoutInterval = 10000, + refreshInterval = REFRESHINTERVAL, + timeoutInterval = TIMEOUTINTERVAL, enableAutoReporting = true, }: FPConfig) { super(); @@ -98,6 +101,29 @@ class FeatureProbe extends TinyEmitter { } } + public static newForTest(toggles: { [key: string]: boolean }): FeatureProbe { + const fp = new FeatureProbe({ + remoteUrl: "http://127.0.0.1:4000", + clientSdkKey: "_", + user: new FPUser(), + timeoutInterval: 1000, + }); + const _toggles: { [key: string]: FPDetail } = {}; + for (const key in toggles) { + const value = toggles[key]; + _toggles[key] = { + value: value, + ruleIndex: null, + variationIndex: null, + version: 0, + reason: "", + }; + } + fp.toggles = _toggles; + fp.successInitialized(); + return fp; + } + /** * Start the FeatureProbe client. */ @@ -339,29 +365,6 @@ class FeatureProbe extends TinyEmitter { }); } - static newForTest(toggles: { [key: string]: boolean }): FeatureProbe { - const fp = new FeatureProbe({ - remoteUrl: "http://127.0.0.1:4000", - clientSdkKey: "_", - user: new FPUser(), - timeoutInterval: 1000, - }); - const _toggles: { [key: string]: FPDetail } = {}; - for (const key in toggles) { - const value = toggles[key]; - _toggles[key] = { - value: value, - ruleIndex: null, - variationIndex: null, - version: 0, - reason: "", - }; - } - fp.toggles = _toggles; - fp.successInitialized(); - return fp; - } - private connectSocket() { const socket = io(this.realtimeUrl, { path: this.realtimePath, @@ -395,13 +398,16 @@ class FeatureProbe extends TinyEmitter { if (typeof v == valueType) { const timestamp = Date.now(); + const DEFAULTVARIATIONINDEX = -1; + const DEFAULTVERSION = 0; + this.eventRecorder?.recordAccessEvent({ time: timestamp, key: key, value: detail.value, - index: detail.variationIndex ?? -1, - version: detail.version ?? 0, - reason: detail.reason + index: detail.variationIndex ?? DEFAULTVARIATIONINDEX, + version: detail.version ?? DEFAULTVERSION, + reason: detail.reason, }); if (detail.trackAccessEvents) { @@ -411,9 +417,9 @@ class FeatureProbe extends TinyEmitter { user: this.getUser().getKey(), key: key, value: detail.value, - variationIndex: detail.variationIndex ?? -1, + variationIndex: detail.variationIndex ?? DEFAULTVARIATIONINDEX, ruleIndex: detail.ruleIndex ?? null, - version: detail.version ?? 0, + version: detail.version ?? DEFAULTVERSION, }); } @@ -494,7 +500,7 @@ class FeatureProbe extends TinyEmitter { "Content-Type": "application/json", UA: getPlatform()?.UA, }, { - user: userParam + user: userParam, }, (json: unknown) => { if (this.status !== STATUS.ERROR) { this.toggles = json as { [key: string]: FPDetail; } | undefined; diff --git a/src/autoReportEvents.ts b/src/autoReportEvents.ts index a29ec6e..ac8d67f 100644 --- a/src/autoReportEvents.ts +++ b/src/autoReportEvents.ts @@ -3,15 +3,17 @@ import { FPUser } from "."; import { EventRecorder } from "./EventRecorder"; import { ClickEvent, IEvent, IEventValue, PageViewEvent } from "./types"; +const WATCHURLCHANGEINTERVAL = 300; + // Reference: https://github.com/sindresorhus/escape-string-regexp function escapeStringRegexp(string: string): string { - if (typeof string !== 'string') { - throw new TypeError('Expected a string'); - } + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } - return string - .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') - .replace(/-/g, '\\x2d'); + return string + .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') + .replace(/-/g, '\\x2d'); } /** @@ -54,7 +56,7 @@ export default function reportEvents( clientSdkKey: string, user: FPUser, getEventsUrl: string, - eventRecorder: EventRecorder + eventRecorder: EventRecorder, ): void { let previousUrl: string = window.location.href; let currentUrl; @@ -100,9 +102,8 @@ export default function reportEvents( function getClickEvents(event: MouseEvent, clickEvents: IEventValue[]) { const matchedEvents = []; - for (let i = 0; i < clickEvents.length; i++) { + for (const clickEvent of clickEvents) { let target = event.target; - const clickEvent = clickEvents[i]; const selector = clickEvent.selector; const elements = selector && document.querySelectorAll(selector); @@ -152,8 +153,8 @@ export default function reportEvents( if (clickEvents.length > 0) { cb = function(event: MouseEvent) { const result = getClickEvents(event, clickEvents); - for (let i = 0; i < result.length; i++) { - sendEvents('click', result[i]); + for (const event of result) { + sendEvents('click', event); } }; @@ -196,7 +197,7 @@ export default function reportEvents( */ setInterval(() => { watchUrlChange(); - }, 300); + }, WATCHURLCHANGEINTERVAL); /** * Get events data from Server API diff --git a/test/autoReportEvents.test.ts b/test/autoReportEvents.test.ts index d88c4b7..315e6a4 100644 --- a/test/autoReportEvents.test.ts +++ b/test/autoReportEvents.test.ts @@ -6,6 +6,7 @@ import { FetchMock } from "jest-fetch-mock"; import * as data from "./fixtures/events.json"; const _fetch = fetch as FetchMock; +const FLUSHINTERVAL = 10000; beforeEach(() => {}); @@ -17,19 +18,19 @@ test("report events", (done) => { _fetch.mockResponseOnce(JSON.stringify(data)); const clientSdkKey = 'clientSdkKey'; const eventsUrl = 'http://featureprobe.io/server/event'; - const recorder = new EventRecorder(clientSdkKey, eventsUrl, 10000); + const recorder = new EventRecorder(clientSdkKey, eventsUrl, FLUSHINTERVAL); const user = new FPUser('11111').with("city", "2"); + const DELAY = 100; reportEvents(clientSdkKey, user, eventsUrl, recorder); - setTimeout(() => { document.body.click(); expect(recorder.eventQueue.length).toBe(3); - expect(recorder.eventQueue[0].kind).toBe('pageview'); - expect(recorder.eventQueue[1].kind).toBe('pageview'); - expect(recorder.eventQueue[2].kind).toBe('click'); + expect(recorder.eventQueue.shift()?.kind).toBe('pageview'); + expect(recorder.eventQueue.shift()?.kind).toBe('pageview'); + expect(recorder.eventQueue.shift()?.kind).toBe('click'); done(); - }, 100); + }, DELAY); }); From 7fd1015f5ccb86e0028a04155a26bf013b912336 Mon Sep 17 00:00:00 2001 From: panchongyang Date: Wed, 22 Feb 2023 16:34:26 +0800 Subject: [PATCH 2/2] chore: style code --- src/FeatureProbe.ts | 20 ++++++++++---------- src/autoReportEvents.ts | 4 ++-- test/autoReportEvents.test.ts | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/FeatureProbe.ts b/src/FeatureProbe.ts index 3c0d0e8..fbec056 100644 --- a/src/FeatureProbe.ts +++ b/src/FeatureProbe.ts @@ -23,8 +23,8 @@ const STATUS = { ERROR: "error", }; -const REFRESHINTERVAL = 1000; -const TIMEOUTINTERVAL = 10000; +const REFRESH_INTERVAL = 1000; +const TIMEOUT_INTERVAL = 10000; /** * You can obtainan a client of FeatureProbe, @@ -57,8 +57,8 @@ class FeatureProbe extends TinyEmitter { realtimePath, clientSdkKey, user, - refreshInterval = REFRESHINTERVAL, - timeoutInterval = TIMEOUTINTERVAL, + refreshInterval = REFRESH_INTERVAL, + timeoutInterval = TIMEOUT_INTERVAL, enableAutoReporting = true, }: FPConfig) { super(); @@ -398,15 +398,15 @@ class FeatureProbe extends TinyEmitter { if (typeof v == valueType) { const timestamp = Date.now(); - const DEFAULTVARIATIONINDEX = -1; - const DEFAULTVERSION = 0; + const DEFAULT_VARIATION_INDEX = -1; + const DEFAULT_VERSION = 0; this.eventRecorder?.recordAccessEvent({ time: timestamp, key: key, value: detail.value, - index: detail.variationIndex ?? DEFAULTVARIATIONINDEX, - version: detail.version ?? DEFAULTVERSION, + index: detail.variationIndex ?? DEFAULT_VARIATION_INDEX, + version: detail.version ?? DEFAULT_VERSION, reason: detail.reason, }); @@ -417,9 +417,9 @@ class FeatureProbe extends TinyEmitter { user: this.getUser().getKey(), key: key, value: detail.value, - variationIndex: detail.variationIndex ?? DEFAULTVARIATIONINDEX, + variationIndex: detail.variationIndex ?? DEFAULT_VARIATION_INDEX, ruleIndex: detail.ruleIndex ?? null, - version: detail.version ?? DEFAULTVERSION, + version: detail.version ?? DEFAULT_VERSION, }); } diff --git a/src/autoReportEvents.ts b/src/autoReportEvents.ts index ac8d67f..9100943 100644 --- a/src/autoReportEvents.ts +++ b/src/autoReportEvents.ts @@ -3,7 +3,7 @@ import { FPUser } from "."; import { EventRecorder } from "./EventRecorder"; import { ClickEvent, IEvent, IEventValue, PageViewEvent } from "./types"; -const WATCHURLCHANGEINTERVAL = 300; +const WATCH_URL_CHANGE_INTERVAL = 300; // Reference: https://github.com/sindresorhus/escape-string-regexp function escapeStringRegexp(string: string): string { @@ -197,7 +197,7 @@ export default function reportEvents( */ setInterval(() => { watchUrlChange(); - }, WATCHURLCHANGEINTERVAL); + }, WATCH_URL_CHANGE_INTERVAL); /** * Get events data from Server API diff --git a/test/autoReportEvents.test.ts b/test/autoReportEvents.test.ts index 315e6a4..54c9646 100644 --- a/test/autoReportEvents.test.ts +++ b/test/autoReportEvents.test.ts @@ -6,7 +6,7 @@ import { FetchMock } from "jest-fetch-mock"; import * as data from "./fixtures/events.json"; const _fetch = fetch as FetchMock; -const FLUSHINTERVAL = 10000; +const FLUSH_INTERVAL = 10000; beforeEach(() => {}); @@ -18,7 +18,7 @@ test("report events", (done) => { _fetch.mockResponseOnce(JSON.stringify(data)); const clientSdkKey = 'clientSdkKey'; const eventsUrl = 'http://featureprobe.io/server/event'; - const recorder = new EventRecorder(clientSdkKey, eventsUrl, FLUSHINTERVAL); + const recorder = new EventRecorder(clientSdkKey, eventsUrl, FLUSH_INTERVAL); const user = new FPUser('11111').with("city", "2"); const DELAY = 100;