Skip to content

Commit 521a334

Browse files
committed
Fixed storage, improved settings management
1 parent 53e5799 commit 521a334

25 files changed

+342
-321
lines changed

example/browser/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import { Exceptionless } from "../../node_modules/@exceptionless/browser/dist/in
22
import { divide } from "./math.js";
33
import { TextAreaLogger } from "./text-area-logger.js";
44

5-
Exceptionless.startup(c => {
5+
await Exceptionless.startup(c => {
66
c.useDebugLogger();
77
c.services.log = new TextAreaLogger("logs", c.services.log);
88

99
c.apiKey = "LhhP1C9gijpSKCslHHCvwdSIz298twx271n1l6xw";
1010
c.serverUrl = "http://localhost:5000";
1111
c.updateSettingsWhenIdleInterval = 15000;
12-
c.useLocalStorage();
12+
c.usePersistedQueueStorage = true;
1313
c.setUserIdentity("12345678", "Blake");
1414
c.useSessions();
1515

example/browser/text-area-logger.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ export class TextAreaLogger {
3535
}
3636

3737
log(level, message) {
38+
const formattedMessage = `${new Date().toISOString()} [${level}] ${message}`;
3839
if (this.element) {
39-
this.element.innerHTML += `\n[${level}] ${message}`;
40+
this.element.innerHTML += `\n${formattedMessage}`;
4041
} else {
41-
this.messageBuffer.push(`[${level}] ${message}`)
42+
this.messageBuffer.push(formattedMessage)
4243
}
4344
}
4445
}

example/express/app.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ const app = express()
33

44
import { Exceptionless } from "../../node_modules/@exceptionless/node/dist/index.js";
55

6-
Exceptionless.startup(c => {
6+
await Exceptionless.startup(c => {
77
c.apiKey = "LhhP1C9gijpSKCslHHCvwdSIz298twx271n1l6xw";
88
c.serverUrl = "http://localhost:5000";
99
c.useDebugLogger();
10-
c.useLocalStorage();
1110

1211
c.defaultTags.push("Example", "Node");
1312

package-lock.json

Lines changed: 94 additions & 112 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@
2727
"packages/*"
2828
],
2929
"devDependencies": {
30-
"@typescript-eslint/eslint-plugin": "4.19.0",
31-
"@typescript-eslint/parser": "4.19.0",
32-
"eslint": "7.22.0",
30+
"@typescript-eslint/eslint-plugin": "4.21.0",
31+
"@typescript-eslint/parser": "4.21.0",
32+
"eslint": "7.23.0",
3333
"eslint-plugin-eslint-comments": "3.2.0",
3434
"eslint-plugin-eslint-plugin": "2.3.0",
3535
"eslint-plugin-import": "2.22.1",
36-
"eslint-plugin-jest": "24.3.2",
36+
"eslint-plugin-jest": "24.3.4",
3737
"eslint-plugin-jsdoc": "32.3.0",
3838
"jest": "26.6.3",
3939
"jest-ts-webcompat-resolver": "1.0.0",

packages/browser/package.json

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,24 @@
3333
".": "./dist/index.js",
3434
"./package.json": "./package.json"
3535
},
36+
"jest": {
37+
"moduleFileExtensions": [
38+
"js",
39+
"ts"
40+
],
41+
"moduleNameMapper": {
42+
"^@exceptionless/(.*)$": "<rootDir>/../$1/src"
43+
},
44+
"preset": "ts-jest",
45+
"resolver": "jest-ts-webcompat-resolver",
46+
"testEnvironment": "jsdom"
47+
},
3648
"scripts": {
3749
"build": "tsc -p tsconfig.json && esbuild src/index.ts --bundle --minify --sourcemap --target=es2020 --format=esm --outfile=dist/index.min.js",
3850
"watch": "tsc -p tsconfig.json -w --preserveWatchOutput",
3951
"test": "jest"
4052
},
41-
"sideEffects": [
42-
"dist/index.js"
43-
],
53+
"sideEffects": false,
4454
"devDependencies": {
4555
"@jest/globals": "26.6.2",
4656
"esbuild": "0.8.49",

packages/browser/src/storage/BrowserLocalStorage.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,37 @@ export class BrowserLocalStorage implements IStorage {
99

1010
public clear(): Promise<void> {
1111
for (const key of this.getKeys()) {
12-
window.localStorage.removeItem(key);
12+
localStorage.removeItem(this.getKey(key));
1313
}
1414

1515
return Promise.resolve();
1616
}
1717

1818
public getItem(key: string): Promise<string> {
19-
return Promise.resolve(window.localStorage.getItem(this.getKey(key)));
19+
return Promise.resolve(localStorage.getItem(this.getKey(key)));
2020
}
2121

2222
public key(index: number): Promise<string> {
2323
const keys = this.getKeys();
24-
return Promise.resolve(keys[index]);
24+
return Promise.resolve(index < keys.length ? keys[index] : null);
2525
}
2626

2727
public keys(): Promise<string[]> {
2828
return Promise.resolve(this.getKeys());
2929
}
3030

3131
public removeItem(key: string): Promise<void> {
32-
window.localStorage.removeItem(this.getKey(key));
32+
localStorage.removeItem(this.getKey(key));
3333
return Promise.resolve();
3434
}
3535

3636
public setItem(key: string, value: string): Promise<void> {
37-
window.localStorage.setItem(this.getKey(key), value);
37+
localStorage.setItem(this.getKey(key), value);
3838
return Promise.resolve();
3939
}
4040

4141
private getKeys(): string[] {
42-
return Object.keys(window.localStorage)
42+
return Object.keys(localStorage)
4343
.filter(key => key.startsWith(this.prefix))
4444
.map(key => key?.substr(this.prefix.length));
4545
}

packages/browser/test/storage/BrowserLocalStorage.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { describeStorage } from "@exceptionless/core/test/storage/InMemoryStorage.test";
2-
import { IStorage } from "@exceptionless/core/src/storage/IStorage";
1+
import { IStorage } from "@exceptionless/core";
2+
import { describeStorage } from "../../../core/test/storage/StorageTestBase.js";
33
import { BrowserLocalStorage } from "../../src/storage/BrowserLocalStorage.js";
44

55
function resetLocalStorage() {

packages/core/src/ExceptionlessClient.ts

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,42 +26,55 @@ export class ExceptionlessClient {
2626
}
2727

2828
this.config.services.queue.onEventsPosted(() => Promise.resolve(this.updateSettingsTimer()));
29+
await SettingsManager.applySavedServerSettings(this.config);
2930
}
3031

31-
this.updateSettingsTimer(configurationOrApiKey ? 5000 : 0);
32+
this.updateSettingsTimer(!!configurationOrApiKey);
3233
await EventPluginManager.startup(new PluginContext(this));
33-
await this.processQueue();
34+
const { queue } = this.config.services;
35+
await queue.startup();
36+
if (this.config.usePersistedQueueStorage) {
37+
// TODO: Can we schedule this as part of startup?
38+
await queue.process();
39+
}
3440
}
3541

3642
/** Submit events, pause any timers and go into low power mode. */
3743
public async suspend(): Promise<void> {
3844
await EventPluginManager.suspend(new PluginContext(this));
39-
await this.processQueue();
40-
await this.config.services.queue.suspend();
41-
this.updateSettingsTimer(0, -1);
45+
const { queue } = this.config.services;
46+
await queue.suspend();
47+
await queue.process();
48+
this.suspendSettingsTimer();
49+
}
50+
51+
private suspendSettingsTimer(): void {
52+
this._timeoutId = clearTimeout(this._timeoutId);
53+
this._intervalId = clearInterval(this._intervalId);
4254
}
4355

4456
public async processQueue(): Promise<void> {
4557
await this.config.services.queue.process();
4658
}
4759

48-
// TODO: Look into better async scheduling..
49-
private updateSettingsTimer(initialDelay: number = 0, updateWhenIdleInterval?: number) {
50-
this._timeoutId = clearTimeout(this._timeoutId);
51-
this._intervalId = clearInterval(this._intervalId);
60+
private updateSettingsTimer(startingUp: boolean = false) {
61+
this.suspendSettingsTimer();
5262

53-
const interval = updateWhenIdleInterval || this.config.updateSettingsWhenIdleInterval;
63+
const interval = this.config.updateSettingsWhenIdleInterval;
5464
if (interval > 0) {
65+
let initialDelay: number = interval;
66+
if (startingUp) {
67+
initialDelay = this.config.settingsVersion > 0 ? 15000 : 5000;
68+
}
69+
5570
this.config.services.log.info(`Update settings every ${interval}ms (${initialDelay || 0}ms delay)`);
56-
// TODO: Fix awaiting promise.
71+
// TODO: Look into better async scheduling..
5772
const updateSettings = () => void SettingsManager.updateSettings(this.config);
58-
if (initialDelay > 0) {
73+
if (initialDelay < interval) {
5974
this._timeoutId = setTimeout(updateSettings, initialDelay);
6075
}
6176

6277
this._intervalId = setInterval(updateSettings, interval);
63-
} else {
64-
this.config.services.log.info("Turning off update settings");
6578
}
6679
}
6780

packages/core/src/configuration/Configuration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export class Configuration {
8181
* the client and will be automatically updated from the server.
8282
*/
8383
public settings: Record<string, string> = {};
84+
public settingsVersion: number = 0;
8485

8586
/**
8687
* The API key that will be used when sending events to the server.

0 commit comments

Comments
 (0)