@arcadible/sdk 1.2.0 → 1.2.1

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.
@@ -3,6 +3,7 @@ export type IndexedDBOptions = {
3
3
  factory?: IDBFactory | null;
4
4
  player?: string;
5
5
  persist?: boolean;
6
+ reopenWait?: number;
6
7
  };
7
8
  export declare function indexedDBBackend(options?: IndexedDBOptions): Backend & {
8
9
  close(): void;
@@ -13,6 +13,9 @@ const CHANNEL = "arcadible-saves";
13
13
  // every save is a guest's for One; a signed-in player's sit beside them
14
14
  // later, under their own id, with no migration.
15
15
  const GUEST = "guest";
16
+ // after a failed reopen, how long calls fail at once before it's tried again,
17
+ // so a game saving every frame doesn't try, and fail, every frame.
18
+ const REOPEN_WAIT = 1000;
16
19
  // [function]
17
20
  function settle(request) {
18
21
  return new Promise((resolve, reject) => {
@@ -66,7 +69,7 @@ function isClosed(err) {
66
69
  // refuses to open (a browser blocking site data, some `file://` pages),
67
70
  // they're kept in memory, and `status()` says so. Once it has opened, it
68
71
  // never switches: a lost connection fails calls with `unavailable` until it
69
- // opens again, rather than show an empty copy.
72
+ // opens again, trying at most once a second, rather than show an empty copy.
70
73
  export function indexedDBBackend(options = {}) {
71
74
  const factory = options.factory === undefined
72
75
  ? (globalThis.indexedDB ?? null)
@@ -79,6 +82,9 @@ export function indexedDBBackend(options = {}) {
79
82
  let opened = false;
80
83
  let current = null;
81
84
  let opening = null;
85
+ // whether reopening has failed since it last worked, and when to try again.
86
+ let down = false;
87
+ let retryAt = 0;
82
88
  let asked = false;
83
89
  const keyOf = (scope) => `${player}\u0000${scope.game}\u0000${scope.channel}`;
84
90
  const rangeOf = (scope) => IDBKeyRange.only([player, scope.game, scope.channel]);
@@ -86,6 +92,7 @@ export function indexedDBBackend(options = {}) {
86
92
  if (current === db)
87
93
  current = null;
88
94
  };
95
+ const unreachable = () => new ArcadibleError(Codes.Unavailable, "Saves can't be reached right now. Try again.");
89
96
  const connect = async function () {
90
97
  try {
91
98
  if (!factory)
@@ -103,13 +110,19 @@ export function indexedDBBackend(options = {}) {
103
110
  globalThis.navigator?.storage?.persist?.().catch(() => false);
104
111
  }
105
112
  opened = true;
113
+ down = false;
106
114
  current = db;
107
115
  return db;
108
116
  }
109
117
  catch (err) {
110
118
  if (opened) {
111
- log("warn", "the saves' storage couldn't be opened again.", err);
112
- throw new ArcadibleError(Codes.Unavailable, "Saves can't be reached right now. Try again.");
119
+ // once until it works again: the calls failing meanwhile say so.
120
+ if (!down) {
121
+ log("warn", "the saves' storage couldn't be opened again.", err);
122
+ }
123
+ down = true;
124
+ retryAt = Date.now() + (options.reopenWait ?? REOPEN_WAIT);
125
+ throw unreachable();
113
126
  }
114
127
  log("warn", "this browser won't keep saves here, so they're kept in memory until the page closes.", err);
115
128
  status = "memory";
@@ -125,6 +138,9 @@ export function indexedDBBackend(options = {}) {
125
138
  return Promise.resolve(null);
126
139
  if (current)
127
140
  return Promise.resolve(current);
141
+ if (down && !opening && Date.now() < retryAt) {
142
+ return Promise.reject(unreachable());
143
+ }
128
144
  opening ??= connect();
129
145
  return opening;
130
146
  };
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "1.2.0";
1
+ export declare const VERSION = "1.2.1";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // The client's version, sent in its hello and shown as `arcadible.version`,
2
2
  // for bug reports. It matches package.json (test/unit/protocol.test.ts).
3
- export const VERSION = "1.2.0";
3
+ export const VERSION = "1.2.1";
package/package.json CHANGED
@@ -43,5 +43,5 @@
43
43
  ],
44
44
  "type": "module",
45
45
  "types": "./dist/index.d.ts",
46
- "version": "1.2.0"
46
+ "version": "1.2.1"
47
47
  }