@smartico/public-api 0.0.402 → 0.0.403

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartico/public-api",
3
- "version": "0.0.402",
3
+ "version": "0.0.403",
4
4
  "description": "Smartico public API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/NodeCache.ts CHANGED
@@ -39,6 +39,14 @@ class NodeCache {
39
39
  }
40
40
  }
41
41
 
42
+ public removeByPrefix(prefix: string) {
43
+ for (const key in this.cache) {
44
+ if (this.cache.hasOwnProperty(key) && key.indexOf(prefix) === 0) {
45
+ delete this.cache[key];
46
+ }
47
+ }
48
+ }
49
+
42
50
  public flushAll() {
43
51
  this.cache = {};
44
52
  if (this.ttlChecker) {
package/src/OCache.ts CHANGED
@@ -56,6 +56,23 @@ export class OCache {
56
56
  }
57
57
  }
58
58
 
59
+ /**
60
+ * Remove every entry whose string key starts with `oKeyBase` — the bare key
61
+ * AND all per-parameter composite variants (`${oKeyBase}:…` / `${oKeyBase}<id>`).
62
+ * Use when a cache is keyed per parameter (paginated, per-template, per-window):
63
+ * an exact-key `clear(oKeyBase)` would miss every variant. `oKeyBase` must be a string.
64
+ */
65
+ public static async clearByPrefix(cacheContext: ECacheContext, oKeyBase: string) {
66
+ // `set`/`get` build keys as `<context>_<JSON.stringify(oKey)>`; JSON.stringify
67
+ // wraps a string in quotes, so dropping the trailing quote yields a prefix that
68
+ // matches both the bare `"base"` key and every `"base…"` composite key.
69
+ const prefix = cacheContext.toString() + '_' + JSON.stringify(oKeyBase).slice(0, -1);
70
+
71
+ if (this.cache[cacheContext]) {
72
+ this.cache[cacheContext].removeByPrefix(prefix);
73
+ }
74
+ }
75
+
59
76
  public static async clearContext(cacheContext: ECacheContext) {
60
77
  if (this.cache[cacheContext]) {
61
78
  this.cache[cacheContext].flushAll();
@@ -34,11 +34,11 @@ export class WSAPI extends WSAPIInbox {
34
34
  on(ClassId.SAW_SHOW_SPIN_PUSH, () => this.reloadMiniGameTemplate());
35
35
  on(ClassId.SAW_AKNOWLEDGE_RESPONSE, () => {
36
36
  this.reloadMiniGameTemplate();
37
- OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.SAWHistory);
37
+ OCache.clearByPrefix(ECacheContext.WSAPI, onUpdateContextKey.SAWHistory);
38
38
  });
39
39
  on(ClassId.SAW_DO_SPIN_RESPONSE, () => {
40
40
  this.reloadMiniGameTemplate();
41
- OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.SAWHistory);
41
+ OCache.clearByPrefix(ECacheContext.WSAPI, onUpdateContextKey.SAWHistory);
42
42
  });
43
43
  on(ClassId.MISSION_OPTIN_RESPONSE, () => this.updateMissions());
44
44
  on(ClassId.ACHIEVEMENT_CLAIM_PRIZE_RESPONSE, () => this.updateMissions());
@@ -57,7 +57,7 @@ export class WSAPI extends WSAPIInbox {
57
57
  on(ClassId.CLAIM_BONUS_RESPONSE, () => this.updateBonuses());
58
58
  on(ClassId.SAW_DO_SPIN_BATCH_RESPONSE, () => {
59
59
  this.reloadMiniGameTemplate();
60
- OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.SAWHistory);
60
+ OCache.clearByPrefix(ECacheContext.WSAPI, onUpdateContextKey.SAWHistory);
61
61
  });
62
62
  on(ClassId.RAF_CLAIM_PRIZE_RESPONSE, () => this.updateRaffles());
63
63
  on(ClassId.GET_INBOX_MESSAGES_RESPONSE, (res) => {
@@ -25,7 +25,10 @@ export class WSAPIJackpots extends WSAPIClans {
25
25
  protected async jackpotClearCache() {
26
26
  OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.Jackpots);
27
27
  OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.Pots);
28
- OCache.clear(ECacheContext.WSAPI, onUpdateContextKey.JackpotWinners);
28
+ // Winners + eligible-games are cached per jp_template_id (composite keys),
29
+ // so a bare clear misses every variant — clear by prefix.
30
+ OCache.clearByPrefix(ECacheContext.WSAPI, onUpdateContextKey.JackpotWinners);
31
+ OCache.clearByPrefix(ECacheContext.WSAPI, onUpdateContextKey.JackpotEligibleGames);
29
32
  }
30
33
 
31
34
  /**
@@ -198,7 +198,7 @@ export class WSAPIMiniGames extends WSAPIRaffles {
198
198
  saw_template_id?: number;
199
199
  }): Promise<TSawHistory[]> {
200
200
  return OCache.use(
201
- onUpdateContextKey.SAWHistory,
201
+ `${onUpdateContextKey.SAWHistory}:${saw_template_id ?? ''}:${limit ?? ''}:${offset ?? ''}`,
202
202
  ECacheContext.WSAPI,
203
203
  () => this.api.getSawWinningHistoryT(this.userExtId, limit, offset, saw_template_id),
204
204
  CACHE_DATA_SEC,
@@ -595,23 +595,48 @@ export class WSAPIUser extends WSAPIBase {
595
595
  onUpdate?: (data: TActivityLog[]) => void;
596
596
  }): Promise<TActivityLog[]> {
597
597
 
598
+ const cacheKey = `${onUpdateContextKey.ActivityLog}:${startTimeSeconds}:${endTimeSeconds}:${from}:${to}`;
599
+
598
600
  if (typeof onUpdate === 'function') {
599
601
  this.onUpdateCallback.set(onUpdateContextKey.ActivityLog, onUpdate);
602
+ // Remember the requested window so a push refresh re-fetches THIS window
603
+ // and writes the matching composite cache key (see notifyActivityLogUpdate).
604
+ this.activityLogOnUpdateParams = { startTimeSeconds, endTimeSeconds, from, to };
600
605
  }
601
606
 
602
607
  return await OCache.use(
603
- onUpdateContextKey.ActivityLog,
608
+ cacheKey,
604
609
  ECacheContext.WSAPI,
605
610
  () => this.api.getActivityLogT(this.userExtId, startTimeSeconds, endTimeSeconds, from, to),
606
611
  CACHE_DATA_SEC,
607
612
  );
608
613
  }
609
614
 
615
+ /** @hidden Last window passed to `getActivityLog` with an `onUpdate`, so a push
616
+ * refresh re-fetches the same window and updates its matching composite cache key. */
617
+ private activityLogOnUpdateParams: { startTimeSeconds: number; endTimeSeconds: number; from: number; to: number } | undefined;
618
+
610
619
  protected async notifyActivityLogUpdate() {
611
- const startSeconds = Date.now() / 1000 - 600;
612
- const endSeconds = Date.now() / 1000;
613
- const payload = await this.api.getActivityLogT(this.userExtId, startSeconds, endSeconds, 0, 50);
620
+ const params = this.activityLogOnUpdateParams;
621
+ // No consumer has subscribed to a specific window yet — nothing to refresh.
622
+ if (!params) {
623
+ return;
624
+ }
625
+
626
+ const payload = await this.api.getActivityLogT(
627
+ this.userExtId,
628
+ params.startTimeSeconds,
629
+ params.endTimeSeconds,
630
+ params.from,
631
+ params.to,
632
+ );
633
+ const cacheKey = `${onUpdateContextKey.ActivityLog}:${params.startTimeSeconds}:${params.endTimeSeconds}:${params.from}:${params.to}`;
634
+
635
+ OCache.set(cacheKey, payload, ECacheContext.WSAPI);
614
636
 
615
- this.updateEntity(onUpdateContextKey.ActivityLog, payload);
637
+ const onUpdate = this.onUpdateCallback.get(onUpdateContextKey.ActivityLog);
638
+ if (typeof onUpdate === 'function') {
639
+ onUpdate(payload);
640
+ }
616
641
  }
617
642
  }