diff options
Diffstat (limited to 'packages/main/src/controllers/ConfigController.ts')
-rw-r--r-- | packages/main/src/controllers/ConfigController.ts | 105 |
1 files changed, 44 insertions, 61 deletions
diff --git a/packages/main/src/controllers/ConfigController.ts b/packages/main/src/controllers/ConfigController.ts index 6690548..a28746c 100644 --- a/packages/main/src/controllers/ConfigController.ts +++ b/packages/main/src/controllers/ConfigController.ts | |||
@@ -25,56 +25,62 @@ import { | |||
25 | IDisposer, | 25 | IDisposer, |
26 | onSnapshot, | 26 | onSnapshot, |
27 | } from 'mobx-state-tree'; | 27 | } from 'mobx-state-tree'; |
28 | import ms from 'ms'; | ||
29 | 28 | ||
30 | import { ConfigPersistenceService } from '../services/ConfigPersistenceService'; | 29 | import type { ConfigPersistenceService } from '../services/ConfigPersistenceService'; |
31 | import { Config, ConfigSnapshotOut } from '../stores/Config'; | 30 | import type { Config, ConfigSnapshotOut } from '../stores/Config'; |
32 | 31 | ||
33 | const DEFAULT_DEBOUNCE_TIME = ms('1s'); | 32 | export class ConfigController { |
33 | static inject = ['configPersistenceService', 'configDebounceTime'] as const; | ||
34 | 34 | ||
35 | class ConfigController { | 35 | private config: Config | null = null; |
36 | readonly #config: Config; | ||
37 | 36 | ||
38 | readonly #persistenceService: ConfigPersistenceService; | 37 | private onSnapshotDisposer: IDisposer | null = null; |
39 | 38 | ||
40 | readonly #onSnapshotDisposer: IDisposer; | 39 | private lastSnapshotOnDisk: ConfigSnapshotOut | null = null; |
41 | 40 | ||
42 | readonly #watcherDisposer: IDisposer; | 41 | private writingConfig: boolean = false; |
43 | 42 | ||
44 | #lastSnapshotOnDisk: ConfigSnapshotOut | null = null; | 43 | constructor( |
44 | private readonly persistenceService: ConfigPersistenceService, | ||
45 | private readonly debounceTime: number, | ||
46 | ) { | ||
47 | } | ||
45 | 48 | ||
46 | #writingConfig: boolean = false; | 49 | async initConfig(config: Config): Promise<void> { |
50 | this.config = config; | ||
47 | 51 | ||
48 | #configMTime: Date | null = null; | 52 | const foundConfig: boolean = await this.readConfig(); |
53 | if (!foundConfig) { | ||
54 | console.log('Creating new config file'); | ||
55 | try { | ||
56 | await this.writeConfig(); | ||
57 | } catch (err) { | ||
58 | console.error('Failed to initialize config'); | ||
59 | } | ||
60 | } | ||
49 | 61 | ||
50 | constructor( | 62 | this.onSnapshotDisposer = onSnapshot(this.config, debounce((snapshot) => { |
51 | config: Config, | ||
52 | persistenceService: ConfigPersistenceService, | ||
53 | debounceTime: number, | ||
54 | ) { | ||
55 | this.#config = config; | ||
56 | this.#persistenceService = persistenceService; | ||
57 | this.#onSnapshotDisposer = onSnapshot(this.#config, debounce((snapshot) => { | ||
58 | // We can compare snapshots by reference, since it is only recreated on store changes. | 63 | // We can compare snapshots by reference, since it is only recreated on store changes. |
59 | if (this.#lastSnapshotOnDisk !== snapshot) { | 64 | if (this.lastSnapshotOnDisk !== snapshot) { |
60 | this.#writeConfig().catch((err) => { | 65 | this.writeConfig().catch((err) => { |
61 | console.log('Failed to write config on config change', err); | 66 | console.log('Failed to write config on config change', err); |
62 | }) | 67 | }) |
63 | } | 68 | } |
64 | }, debounceTime)); | 69 | }, this.debounceTime)); |
65 | this.#watcherDisposer = this.#persistenceService.watchConfig(async (mtime) => { | 70 | |
66 | if (!this.#writingConfig && (this.#configMTime === null || mtime > this.#configMTime)) { | 71 | this.persistenceService.watchConfig(async () => { |
67 | await this.#readConfig(); | 72 | if (!this.writingConfig) { |
73 | await this.readConfig(); | ||
68 | } | 74 | } |
69 | }, debounceTime); | 75 | }, this.debounceTime); |
70 | } | 76 | } |
71 | 77 | ||
72 | async #readConfig(): Promise<boolean> { | 78 | private async readConfig(): Promise<boolean> { |
73 | const result = await this.#persistenceService.readConfig(); | 79 | const result = await this.persistenceService.readConfig(); |
74 | if (result.found) { | 80 | if (result.found) { |
75 | try { | 81 | try { |
76 | applySnapshot(this.#config, result.data); | 82 | applySnapshot(this.config!, result.data); |
77 | this.#lastSnapshotOnDisk = getSnapshot(this.#config); | 83 | this.lastSnapshotOnDisk = getSnapshot(this.config!); |
78 | console.log('Loaded config'); | 84 | console.log('Loaded config'); |
79 | } catch (err) { | 85 | } catch (err) { |
80 | console.error('Failed to read config', result.data, err); | 86 | console.error('Failed to read config', result.data, err); |
@@ -83,42 +89,19 @@ class ConfigController { | |||
83 | return result.found; | 89 | return result.found; |
84 | } | 90 | } |
85 | 91 | ||
86 | async #writeConfig(): Promise<void> { | 92 | private async writeConfig(): Promise<void> { |
87 | const snapshot = getSnapshot(this.#config); | 93 | const snapshot = getSnapshot(this.config!); |
88 | this.#writingConfig = true; | 94 | this.writingConfig = true; |
89 | try { | 95 | try { |
90 | this.#configMTime = await this.#persistenceService.writeConfig(snapshot); | 96 | await this.persistenceService.writeConfig(snapshot); |
91 | this.#lastSnapshotOnDisk = snapshot; | 97 | this.lastSnapshotOnDisk = snapshot; |
92 | console.log('Wrote config'); | 98 | console.log('Wrote config'); |
93 | } finally { | 99 | } finally { |
94 | this.#writingConfig = false; | 100 | this.writingConfig = false; |
95 | } | ||
96 | } | ||
97 | |||
98 | async initConfig(): Promise<void> { | ||
99 | const foundConfig: boolean = await this.#readConfig(); | ||
100 | if (!foundConfig) { | ||
101 | console.log('Creating new config file'); | ||
102 | try { | ||
103 | await this.#writeConfig(); | ||
104 | } catch (err) { | ||
105 | console.error('Failed to initialize config'); | ||
106 | } | ||
107 | } | 101 | } |
108 | } | 102 | } |
109 | 103 | ||
110 | dispose(): void { | 104 | dispose(): void { |
111 | this.#onSnapshotDisposer(); | 105 | this.onSnapshotDisposer?.(); |
112 | this.#watcherDisposer(); | ||
113 | } | 106 | } |
114 | } | 107 | } |
115 | |||
116 | export async function initConfig( | ||
117 | config: Config, | ||
118 | persistenceService: ConfigPersistenceService, | ||
119 | debounceTime: number = DEFAULT_DEBOUNCE_TIME, | ||
120 | ): Promise<IDisposer> { | ||
121 | const controller = new ConfigController(config, persistenceService, debounceTime); | ||
122 | await controller.initConfig(); | ||
123 | return () => controller.dispose(); | ||
124 | } | ||