|
1 | | -<<<<<<< HEAD |
2 | | -<<<<<<< HEAD |
3 | 1 | import { Logger as ILogger } from '@amplitude/analytics-types'; |
4 | | -======= |
5 | | -import { Logger as ILogger, SpecialEventType } from '@amplitude/analytics-types'; |
6 | | ->>>>>>> 3e83ab49 (feat(session replay): add ability to target on multiple events) |
7 | | -======= |
8 | | -import { Logger as ILogger } from '@amplitude/analytics-types'; |
9 | | ->>>>>>> 79705348 (test(targeting + session replay): get test coverage up to 100%) |
10 | 2 | import { DBSchema, IDBPDatabase, IDBPTransaction, openDB } from 'idb'; |
11 | 3 |
|
12 | 4 | export const MAX_IDB_STORAGE_LENGTH = 1000 * 60 * 60 * 24 * 2; // 2 days |
13 | 5 |
|
14 | | -<<<<<<< HEAD |
15 | | -<<<<<<< HEAD |
16 | | -======= |
17 | | ->>>>>>> 7ea29d5c (fix(targeting): keep track of open db instances and ensure deduplication of events) |
18 | 6 | // This type is constructed to allow for future proofing - in the future we may want |
19 | 7 | // to track how many of each event is fired, and we may want to track event properties |
20 | 8 | // Any further fields, like event properties, can be added to this type without causing |
21 | 9 | // a breaking change |
22 | 10 | type EventData = { event_type: string }; |
23 | 11 |
|
24 | 12 | type EventTypeStore = { [event_type: string]: { [timestamp: number]: EventData } }; |
25 | | -<<<<<<< HEAD |
26 | | -======= |
27 | | ->>>>>>> 3e83ab49 (feat(session replay): add ability to target on multiple events) |
28 | | -======= |
29 | | ->>>>>>> 7ea29d5c (fix(targeting): keep track of open db instances and ensure deduplication of events) |
30 | 13 | export interface TargetingDB extends DBSchema { |
31 | 14 | eventTypesForSession: { |
32 | 15 | key: number; |
33 | 16 | value: { |
34 | 17 | sessionId: number; |
35 | | -<<<<<<< HEAD |
36 | | -<<<<<<< HEAD |
37 | | -<<<<<<< HEAD |
38 | | - eventTypes: EventTypeStore; |
39 | | -======= |
40 | | - eventTypes: Set<string>; |
41 | | ->>>>>>> 3e83ab49 (feat(session replay): add ability to target on multiple events) |
42 | | -======= |
43 | | - eventTypes: Array<{ event_type: string }>; |
44 | | ->>>>>>> 79705348 (test(targeting + session replay): get test coverage up to 100%) |
45 | | -======= |
46 | 18 | eventTypes: EventTypeStore; |
47 | | ->>>>>>> 7ea29d5c (fix(targeting): keep track of open db instances and ensure deduplication of events) |
48 | 19 | }; |
49 | 20 | }; |
50 | 21 | } |
51 | 22 |
|
52 | | -<<<<<<< HEAD |
53 | | -<<<<<<< HEAD |
54 | 23 | export class TargetingIDBStore { |
55 | 24 | dbs: { [apiKey: string]: IDBPDatabase<TargetingDB> } = {}; |
56 | 25 |
|
@@ -177,155 +146,3 @@ export class TargetingIDBStore { |
177 | 146 | } |
178 | 147 |
|
179 | 148 | export const targetingIDBStore = new TargetingIDBStore(); |
180 | | -======= |
181 | | -export const createStore = async (dbName: string) => { |
182 | | - return await openDB<TargetingDB>(dbName, 1, { |
183 | | - upgrade: (db: IDBPDatabase<TargetingDB>) => { |
184 | | - if (!db.objectStoreNames.contains('eventTypesForSession')) { |
185 | | - db.createObjectStore('eventTypesForSession', { |
186 | | - keyPath: 'sessionId', |
187 | | - }); |
188 | | - } |
189 | | - }, |
190 | | - }); |
191 | | -}; |
192 | | -======= |
193 | | -export class TargetingIDBStore { |
194 | | - dbs: { [apiKey: string]: IDBPDatabase<TargetingDB> } | undefined; |
195 | | ->>>>>>> 7ea29d5c (fix(targeting): keep track of open db instances and ensure deduplication of events) |
196 | | - |
197 | | - createStore = async (dbName: string) => { |
198 | | - return await openDB<TargetingDB>(dbName, 1, { |
199 | | - upgrade: (db: IDBPDatabase<TargetingDB>) => { |
200 | | - if (!db.objectStoreNames.contains('eventTypesForSession')) { |
201 | | - db.createObjectStore('eventTypesForSession', { |
202 | | - keyPath: 'sessionId', |
203 | | - }); |
204 | | - } |
205 | | - }, |
206 | | - }); |
207 | | - }; |
208 | | - |
209 | | - openOrCreateDB = async (apiKey: string) => { |
210 | | - if (this.dbs && this.dbs[apiKey]) { |
211 | | - return this.dbs[apiKey]; |
212 | | - } |
213 | | - const dbName = `${apiKey.substring(0, 10)}_amp_targeting`; |
214 | | - const db = await this.createStore(dbName); |
215 | | - this.dbs = { |
216 | | - ...this.dbs, |
217 | | - [apiKey]: db, |
218 | | - }; |
219 | | - return db; |
220 | | - }; |
221 | | - |
222 | | - updateEventListForSession = async ({ |
223 | | - sessionId, |
224 | | - eventType, |
225 | | - eventTime, |
226 | | - loggerProvider, |
227 | | - tx, |
228 | | - }: { |
229 | | - sessionId: number; |
230 | | - eventType: string; |
231 | | - eventTime: number; |
232 | | - loggerProvider: ILogger; |
233 | | - tx: IDBPTransaction<TargetingDB, ['eventTypesForSession'], 'readwrite'>; |
234 | | - }) => { |
235 | | - try { |
236 | | - const eventTypesForSessionStorage = await tx.store.get(sessionId); |
237 | | - const eventTypesForSession = eventTypesForSessionStorage ? eventTypesForSessionStorage.eventTypes : {}; |
238 | | - const eventTypeStore = eventTypesForSession[eventType] || {}; |
239 | | - |
240 | | - const updatedEventTypes: EventTypeStore = { |
241 | | - ...eventTypesForSession, |
242 | | - [eventType]: { |
243 | | - ...eventTypeStore, |
244 | | - [eventTime]: { event_type: eventType }, |
245 | | - }, |
246 | | - }; |
247 | | - await tx.store.put({ sessionId, eventTypes: updatedEventTypes }); |
248 | | - return updatedEventTypes; |
249 | | - } catch (e) { |
250 | | - loggerProvider.warn(`Failed to store events for targeting ${sessionId}: ${e as string}`); |
251 | | - } |
252 | | - return undefined; |
253 | | - }; |
254 | | - |
255 | | - deleteOldSessionEventTypes = async ({ |
256 | | - currentSessionId, |
257 | | - loggerProvider, |
258 | | - tx, |
259 | | - }: { |
260 | | - currentSessionId: number; |
261 | | - loggerProvider: ILogger; |
262 | | - tx: IDBPTransaction<TargetingDB, ['eventTypesForSession'], 'readwrite'>; |
263 | | - }) => { |
264 | | - try { |
265 | | - const allEventTypeObjs = await tx.store.getAll(); |
266 | | - for (let i = 0; i < allEventTypeObjs.length; i++) { |
267 | | - const eventTypeObj = allEventTypeObjs[i]; |
268 | | - const amountOfTimeSinceSession = Date.now() - eventTypeObj.sessionId; |
269 | | - if (eventTypeObj.sessionId !== currentSessionId && amountOfTimeSinceSession > MAX_IDB_STORAGE_LENGTH) { |
270 | | - await tx.store.delete(eventTypeObj.sessionId); |
271 | | - } |
272 | | - } |
273 | | - } catch (e) { |
274 | | - loggerProvider.warn(`Failed to clear old session events for targeting: ${e as string}`); |
275 | | - } |
276 | | - }; |
277 | | - |
278 | | - storeEventTypeForSession = async ({ |
279 | | - loggerProvider, |
280 | | - sessionId, |
281 | | - eventType, |
282 | | - eventTime, |
283 | | - apiKey, |
284 | | - }: { |
285 | | - loggerProvider: ILogger; |
286 | | - apiKey: string; |
287 | | - eventType: string; |
288 | | - eventTime: number; |
289 | | - sessionId: number; |
290 | | - }) => { |
291 | | - try { |
292 | | - const db = await this.openOrCreateDB(apiKey); |
293 | | - |
294 | | - const tx = db.transaction<'eventTypesForSession', 'readwrite'>('eventTypesForSession', 'readwrite'); |
295 | | - if (!tx) { |
296 | | - return; |
297 | | - } |
298 | | - |
299 | | -<<<<<<< HEAD |
300 | | - return updatedEventTypes; |
301 | | - } catch (e) { |
302 | | - loggerProvider.warn(`Failed to store events for targeting ${sessionId}: ${e as string}`); |
303 | | - } |
304 | | - return undefined; |
305 | | -}; |
306 | | ->>>>>>> 3e83ab49 (feat(session replay): add ability to target on multiple events) |
307 | | -======= |
308 | | - // Update the list of events for the session |
309 | | - const updatedEventTypes = await this.updateEventListForSession({ |
310 | | - sessionId, |
311 | | - tx, |
312 | | - loggerProvider, |
313 | | - eventType, |
314 | | - eventTime, |
315 | | - }); |
316 | | - |
317 | | - // Clear out sessions older than 2 days |
318 | | - await this.deleteOldSessionEventTypes({ currentSessionId: sessionId, tx, loggerProvider }); |
319 | | - |
320 | | - await tx.done; |
321 | | - |
322 | | - return updatedEventTypes; |
323 | | - } catch (e) { |
324 | | - loggerProvider.warn(`Failed to store events for targeting ${sessionId}: ${e as string}`); |
325 | | - } |
326 | | - return undefined; |
327 | | - }; |
328 | | -} |
329 | | - |
330 | | -export const targetingIDBStore = new TargetingIDBStore(); |
331 | | ->>>>>>> 7ea29d5c (fix(targeting): keep track of open db instances and ensure deduplication of events) |
0 commit comments