@kapeta/local-cluster-service 0.16.0 → 0.16.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.
- package/CHANGELOG.md +7 -0
- package/dist/cjs/src/RepositoryWatcher.d.ts +4 -3
- package/dist/cjs/src/RepositoryWatcher.js +15 -19
- package/dist/cjs/src/assetManager.d.ts +4 -6
- package/dist/cjs/src/assetManager.js +29 -52
- package/dist/cjs/src/assets/routes.js +2 -2
- package/dist/cjs/src/cacheManager.d.ts +16 -0
- package/dist/cjs/src/cacheManager.js +38 -0
- package/dist/cjs/src/definitionsManager.d.ts +2 -4
- package/dist/cjs/src/definitionsManager.js +7 -21
- package/dist/cjs/src/repositoryManager.d.ts +7 -2
- package/dist/cjs/src/repositoryManager.js +10 -10
- package/dist/cjs/src/types.d.ts +2 -0
- package/dist/cjs/src/utils/utils.js +1 -1
- package/dist/esm/src/RepositoryWatcher.d.ts +4 -3
- package/dist/esm/src/RepositoryWatcher.js +15 -19
- package/dist/esm/src/assetManager.d.ts +4 -6
- package/dist/esm/src/assetManager.js +29 -52
- package/dist/esm/src/assets/routes.js +2 -2
- package/dist/esm/src/cacheManager.d.ts +16 -0
- package/dist/esm/src/cacheManager.js +31 -0
- package/dist/esm/src/definitionsManager.d.ts +2 -4
- package/dist/esm/src/definitionsManager.js +7 -21
- package/dist/esm/src/repositoryManager.d.ts +7 -2
- package/dist/esm/src/repositoryManager.js +10 -10
- package/dist/esm/src/types.d.ts +2 -0
- package/dist/esm/src/utils/utils.js +1 -1
- package/package.json +1 -1
- package/src/RepositoryWatcher.ts +18 -20
- package/src/assetManager.ts +40 -58
- package/src/assets/routes.ts +2 -2
- package/src/cacheManager.ts +45 -0
- package/src/definitionsManager.ts +9 -33
- package/src/repositoryManager.ts +11 -12
- package/src/types.ts +2 -2
- package/src/utils/utils.ts +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Definition } from '@kapeta/local-cluster-config';
|
|
2
2
|
import { BlockDefinition } from '@kapeta/schemas';
|
|
3
|
+
import { SourceOfChange } from './types';
|
|
3
4
|
export interface EnrichedAsset {
|
|
4
5
|
ref: string;
|
|
5
6
|
editable: boolean;
|
|
@@ -11,9 +12,6 @@ export interface EnrichedAsset {
|
|
|
11
12
|
ymlPath: string;
|
|
12
13
|
}
|
|
13
14
|
declare class AssetManager {
|
|
14
|
-
private cache;
|
|
15
|
-
constructor();
|
|
16
|
-
clearCache(): void;
|
|
17
15
|
/**
|
|
18
16
|
*
|
|
19
17
|
* @param {string[]} [assetKinds]
|
|
@@ -23,12 +21,12 @@ declare class AssetManager {
|
|
|
23
21
|
getPlans(): EnrichedAsset[];
|
|
24
22
|
getPlan(ref: string, noCache?: boolean): Promise<Definition>;
|
|
25
23
|
getAsset(ref: string, noCache?: boolean, autoFetch?: boolean): Promise<EnrichedAsset | undefined>;
|
|
26
|
-
createAsset(path: string, yaml: BlockDefinition): Promise<EnrichedAsset[]>;
|
|
27
|
-
updateAsset(ref: string, yaml: BlockDefinition): Promise<void>;
|
|
28
|
-
private maybeGenerateCode;
|
|
24
|
+
createAsset(path: string, yaml: BlockDefinition, sourceOfChange?: SourceOfChange): Promise<EnrichedAsset[]>;
|
|
25
|
+
updateAsset(ref: string, yaml: BlockDefinition, sourceOfChange?: SourceOfChange): Promise<void>;
|
|
29
26
|
importFile(filePath: string): Promise<EnrichedAsset[]>;
|
|
30
27
|
unregisterAsset(ref: string): Promise<void>;
|
|
31
28
|
installAsset(ref: string): Promise<import("./taskManager").Task<void>[] | undefined>;
|
|
29
|
+
private maybeGenerateCode;
|
|
32
30
|
}
|
|
33
31
|
export declare const assetManager: AssetManager;
|
|
34
32
|
export {};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import Path from 'node:path';
|
|
2
2
|
import FS from 'fs-extra';
|
|
3
3
|
import YAML from 'yaml';
|
|
4
|
-
import NodeCache from 'node-cache';
|
|
5
4
|
import { codeGeneratorManager } from './codeGeneratorManager';
|
|
6
5
|
import { ProgressListener } from './progressListener';
|
|
7
6
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
|
@@ -10,10 +9,8 @@ import { Actions } from '@kapeta/nodejs-registry-utils';
|
|
|
10
9
|
import { definitionsManager } from './definitionsManager';
|
|
11
10
|
import { normalizeKapetaUri } from './utils/utils';
|
|
12
11
|
import { taskManager } from './taskManager';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
assetManager.clearCache();
|
|
16
|
-
}
|
|
12
|
+
import { cacheManager } from './cacheManager';
|
|
13
|
+
const CACHE_TTL = 60 * 60 * 1000; // 1 hour
|
|
17
14
|
function enrichAsset(asset) {
|
|
18
15
|
return {
|
|
19
16
|
ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
|
|
@@ -39,15 +36,6 @@ function parseRef(ref) {
|
|
|
39
36
|
return [out[0].toLowerCase(), out[1].toLowerCase()];
|
|
40
37
|
}
|
|
41
38
|
class AssetManager {
|
|
42
|
-
cache;
|
|
43
|
-
constructor() {
|
|
44
|
-
this.cache = new NodeCache({
|
|
45
|
-
stdTTL: 60 * 60, // 1 hour
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
clearCache() {
|
|
49
|
-
this.cache.flushAll();
|
|
50
|
-
}
|
|
51
39
|
/**
|
|
52
40
|
*
|
|
53
41
|
* @param {string[]} [assetKinds]
|
|
@@ -80,8 +68,8 @@ class AssetManager {
|
|
|
80
68
|
async getAsset(ref, noCache = false, autoFetch = true) {
|
|
81
69
|
ref = normalizeKapetaUri(ref);
|
|
82
70
|
const cacheKey = `getAsset:${ref}`;
|
|
83
|
-
if (!noCache &&
|
|
84
|
-
return
|
|
71
|
+
if (!noCache && cacheManager.has(cacheKey)) {
|
|
72
|
+
return cacheManager.get(cacheKey);
|
|
85
73
|
}
|
|
86
74
|
const uri = parseKapetaUri(ref);
|
|
87
75
|
if (autoFetch) {
|
|
@@ -95,11 +83,11 @@ class AssetManager {
|
|
|
95
83
|
throw new Error('Asset not found: ' + ref);
|
|
96
84
|
}
|
|
97
85
|
if (asset) {
|
|
98
|
-
|
|
86
|
+
cacheManager.set(cacheKey, asset, CACHE_TTL);
|
|
99
87
|
}
|
|
100
88
|
return asset;
|
|
101
89
|
}
|
|
102
|
-
async createAsset(path, yaml) {
|
|
90
|
+
async createAsset(path, yaml, sourceOfChange = 'filesystem') {
|
|
103
91
|
if (await FS.pathExists(path)) {
|
|
104
92
|
throw new Error('File already exists: ' + path);
|
|
105
93
|
}
|
|
@@ -107,14 +95,15 @@ class AssetManager {
|
|
|
107
95
|
if (!(await FS.pathExists(dirName))) {
|
|
108
96
|
await FS.mkdirp(dirName);
|
|
109
97
|
}
|
|
98
|
+
await repositoryManager.setSourceOfChangeFor(path, sourceOfChange);
|
|
110
99
|
await FS.writeFile(path, YAML.stringify(yaml));
|
|
111
100
|
const asset = await this.importFile(path);
|
|
112
|
-
|
|
101
|
+
cacheManager.flush();
|
|
113
102
|
const ref = `kapeta://${yaml.metadata.name}:local`;
|
|
114
103
|
this.maybeGenerateCode(ref, path, yaml);
|
|
115
104
|
return asset;
|
|
116
105
|
}
|
|
117
|
-
async updateAsset(ref, yaml) {
|
|
106
|
+
async updateAsset(ref, yaml, sourceOfChange = 'filesystem') {
|
|
118
107
|
const asset = await this.getAsset(ref, true, false);
|
|
119
108
|
if (!asset) {
|
|
120
109
|
throw new Error('Attempted to update unknown asset: ' + ref);
|
|
@@ -125,36 +114,11 @@ class AssetManager {
|
|
|
125
114
|
if (!asset.ymlPath) {
|
|
126
115
|
throw new Error('Attempted to update corrupted asset: ' + ref);
|
|
127
116
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
clearAllCaches();
|
|
134
|
-
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
|
135
|
-
}
|
|
136
|
-
finally {
|
|
137
|
-
//We need to wait a bit for the disk to settle before we can resume watching
|
|
138
|
-
setTimeout(async () => {
|
|
139
|
-
try {
|
|
140
|
-
await repositoryManager.resumeChangedFor(path);
|
|
141
|
-
}
|
|
142
|
-
catch (e) { }
|
|
143
|
-
}, 500);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
maybeGenerateCode(ref, ymlPath, block) {
|
|
147
|
-
ref = normalizeKapetaUri(ref);
|
|
148
|
-
if (codeGeneratorManager.canGenerateCode(block)) {
|
|
149
|
-
const assetTitle = block.metadata.title ? block.metadata.title : parseKapetaUri(block.metadata.name).name;
|
|
150
|
-
taskManager.add(`codegen:${ref}`, async () => {
|
|
151
|
-
await codeGeneratorManager.generate(ymlPath, block);
|
|
152
|
-
}, {
|
|
153
|
-
name: `Generating code for ${assetTitle}`,
|
|
154
|
-
});
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
return false;
|
|
117
|
+
await repositoryManager.setSourceOfChangeFor(asset.ymlPath, sourceOfChange);
|
|
118
|
+
await FS.writeFile(asset.ymlPath, YAML.stringify(yaml));
|
|
119
|
+
console.log('Wrote to ' + asset.ymlPath);
|
|
120
|
+
cacheManager.flush();
|
|
121
|
+
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
|
158
122
|
}
|
|
159
123
|
async importFile(filePath) {
|
|
160
124
|
if (filePath.startsWith('file://')) {
|
|
@@ -168,7 +132,7 @@ class AssetManager {
|
|
|
168
132
|
await Actions.link(new ProgressListener(), Path.dirname(filePath));
|
|
169
133
|
const version = 'local';
|
|
170
134
|
const refs = assetInfos.map((assetInfo) => `kapeta://${assetInfo.metadata.name}:${version}`);
|
|
171
|
-
|
|
135
|
+
cacheManager.flush();
|
|
172
136
|
return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
|
|
173
137
|
}
|
|
174
138
|
async unregisterAsset(ref) {
|
|
@@ -176,7 +140,7 @@ class AssetManager {
|
|
|
176
140
|
if (!asset) {
|
|
177
141
|
throw new Error('Asset does not exists: ' + ref);
|
|
178
142
|
}
|
|
179
|
-
|
|
143
|
+
cacheManager.flush();
|
|
180
144
|
await Actions.uninstall(new ProgressListener(), [asset.ref]);
|
|
181
145
|
}
|
|
182
146
|
async installAsset(ref) {
|
|
@@ -188,5 +152,18 @@ class AssetManager {
|
|
|
188
152
|
console.log('Installing %s', ref);
|
|
189
153
|
return await repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, false);
|
|
190
154
|
}
|
|
155
|
+
maybeGenerateCode(ref, ymlPath, block) {
|
|
156
|
+
ref = normalizeKapetaUri(ref);
|
|
157
|
+
if (codeGeneratorManager.canGenerateCode(block)) {
|
|
158
|
+
const assetTitle = block.metadata.title ? block.metadata.title : parseKapetaUri(block.metadata.name).name;
|
|
159
|
+
taskManager.add(`codegen:${ref}`, async () => {
|
|
160
|
+
await codeGeneratorManager.generate(ymlPath, block);
|
|
161
|
+
}, {
|
|
162
|
+
name: `Generating code for ${assetTitle}`,
|
|
163
|
+
});
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
191
168
|
}
|
|
192
169
|
export const assetManager = new AssetManager();
|
|
@@ -58,7 +58,7 @@ router.post('/create', async (req, res) => {
|
|
|
58
58
|
}
|
|
59
59
|
const content = parseBody(req);
|
|
60
60
|
try {
|
|
61
|
-
const assets = await assetManager.createAsset(req.query.path, content);
|
|
61
|
+
const assets = await assetManager.createAsset(req.query.path, content, 'user');
|
|
62
62
|
res.status(200).send(assets);
|
|
63
63
|
}
|
|
64
64
|
catch (err) {
|
|
@@ -76,7 +76,7 @@ router.put('/update', async (req, res) => {
|
|
|
76
76
|
}
|
|
77
77
|
const content = parseBody(req);
|
|
78
78
|
try {
|
|
79
|
-
await assetManager.updateAsset(req.query.ref, content);
|
|
79
|
+
await assetManager.updateAsset(req.query.ref, content, 'user');
|
|
80
80
|
res.sendStatus(204);
|
|
81
81
|
}
|
|
82
82
|
catch (err) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface CacheEntry<T = any> {
|
|
2
|
+
expires: number;
|
|
3
|
+
data: T;
|
|
4
|
+
}
|
|
5
|
+
declare class CacheManager {
|
|
6
|
+
private cache;
|
|
7
|
+
flush(): void;
|
|
8
|
+
doCached<T>(key: string, getter: () => T, ttl?: number): T;
|
|
9
|
+
get<T>(key: string): T | undefined;
|
|
10
|
+
set<T>(key: string, data: T, ttl?: number): void;
|
|
11
|
+
has(key: string): boolean;
|
|
12
|
+
remove(key: string): number;
|
|
13
|
+
}
|
|
14
|
+
export declare const cacheManager: CacheManager;
|
|
15
|
+
export declare const doCached: <T>(key: string, getter: () => T, ttl?: number) => T;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import NodeCache from 'node-cache';
|
|
2
|
+
const DEFAULT_CACHE_TTL = 60 * 1000; // 1 min
|
|
3
|
+
class CacheManager {
|
|
4
|
+
cache = new NodeCache();
|
|
5
|
+
flush() {
|
|
6
|
+
this.cache.flushAll();
|
|
7
|
+
}
|
|
8
|
+
doCached(key, getter, ttl = DEFAULT_CACHE_TTL) {
|
|
9
|
+
const data = this.cache.get(key);
|
|
10
|
+
if (data !== undefined) {
|
|
11
|
+
return data;
|
|
12
|
+
}
|
|
13
|
+
const result = getter();
|
|
14
|
+
this.cache.set(key, result, ttl);
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
get(key) {
|
|
18
|
+
return this.cache.get(key);
|
|
19
|
+
}
|
|
20
|
+
set(key, data, ttl = DEFAULT_CACHE_TTL) {
|
|
21
|
+
this.cache.set(key, data, ttl);
|
|
22
|
+
}
|
|
23
|
+
has(key) {
|
|
24
|
+
return this.cache.has(key);
|
|
25
|
+
}
|
|
26
|
+
remove(key) {
|
|
27
|
+
return this.cache.del(key);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export const cacheManager = new CacheManager();
|
|
31
|
+
export const doCached = (key, getter, ttl = DEFAULT_CACHE_TTL) => cacheManager.doCached(key, getter, ttl);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { DefinitionInfo } from '@kapeta/local-cluster-config';
|
|
2
2
|
declare class DefinitionsManager {
|
|
3
|
-
private
|
|
4
|
-
private
|
|
5
|
-
clearCache(): void;
|
|
6
|
-
private doCached;
|
|
3
|
+
private getHash;
|
|
4
|
+
private getFullKey;
|
|
7
5
|
getDefinitions(kindFilter?: string | string[]): DefinitionInfo[];
|
|
8
6
|
exists(ref: string): boolean;
|
|
9
7
|
getProviderDefinitions(): DefinitionInfo[];
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
|
2
2
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
|
3
|
-
|
|
3
|
+
import { doCached } from './cacheManager';
|
|
4
4
|
class DefinitionsManager {
|
|
5
|
-
|
|
6
|
-
getKey(kindFilter) {
|
|
5
|
+
getHash(kindFilter) {
|
|
7
6
|
if (kindFilter) {
|
|
8
7
|
if (Array.isArray(kindFilter)) {
|
|
9
8
|
return kindFilter.join(',');
|
|
@@ -12,31 +11,18 @@ class DefinitionsManager {
|
|
|
12
11
|
}
|
|
13
12
|
return 'none';
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
this.
|
|
17
|
-
}
|
|
18
|
-
doCached(key, getter) {
|
|
19
|
-
if (this.cache[key]) {
|
|
20
|
-
if (this.cache[key].expires > Date.now()) {
|
|
21
|
-
return this.cache[key].definitions;
|
|
22
|
-
}
|
|
23
|
-
delete this.cache[key];
|
|
24
|
-
}
|
|
25
|
-
this.cache[key] = {
|
|
26
|
-
expires: Date.now() + CACHE_TTL,
|
|
27
|
-
definitions: getter(),
|
|
28
|
-
};
|
|
29
|
-
return this.cache[key].definitions;
|
|
14
|
+
getFullKey(kindFilter) {
|
|
15
|
+
return `DefinitionsManager:${this.getHash(kindFilter)}`;
|
|
30
16
|
}
|
|
31
17
|
getDefinitions(kindFilter) {
|
|
32
|
-
const key = this.
|
|
33
|
-
return
|
|
18
|
+
const key = this.getFullKey(kindFilter);
|
|
19
|
+
return doCached(key, () => ClusterConfiguration.getDefinitions(kindFilter));
|
|
34
20
|
}
|
|
35
21
|
exists(ref) {
|
|
36
22
|
return !!this.getDefinition(ref);
|
|
37
23
|
}
|
|
38
24
|
getProviderDefinitions() {
|
|
39
|
-
return
|
|
25
|
+
return doCached('providers', () => ClusterConfiguration.getProviderDefinitions());
|
|
40
26
|
}
|
|
41
27
|
getDefinition(ref) {
|
|
42
28
|
const uri = parseKapetaUri(ref);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Task } from './taskManager';
|
|
2
|
+
import { SourceOfChange } from './types';
|
|
2
3
|
declare class RepositoryManager {
|
|
3
4
|
private _registryService;
|
|
4
5
|
private _cache;
|
|
@@ -6,8 +7,12 @@ declare class RepositoryManager {
|
|
|
6
7
|
constructor();
|
|
7
8
|
listenForChanges(): void;
|
|
8
9
|
stopListening(): Promise<void>;
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Setting the source of change helps us know
|
|
12
|
+
* how to react to changes in the UI.
|
|
13
|
+
*/
|
|
14
|
+
setSourceOfChangeFor(file: string, source: SourceOfChange): Promise<void>;
|
|
15
|
+
clearSourceOfChangeFor(file: string): Promise<void>;
|
|
11
16
|
ensureDefaultProviders(): void;
|
|
12
17
|
private _install;
|
|
13
18
|
ensureAsset(handle: string, name: string, version: string, wait?: boolean): Promise<undefined | Task[]>;
|
|
@@ -6,11 +6,7 @@ import { taskManager } from './taskManager';
|
|
|
6
6
|
import { normalizeKapetaUri } from './utils/utils';
|
|
7
7
|
import { ProgressListener } from './progressListener';
|
|
8
8
|
import { RepositoryWatcher } from './RepositoryWatcher';
|
|
9
|
-
import {
|
|
10
|
-
function clearAllCaches() {
|
|
11
|
-
definitionsManager.clearCache();
|
|
12
|
-
assetManager.clearCache();
|
|
13
|
-
}
|
|
9
|
+
import { cacheManager } from './cacheManager';
|
|
14
10
|
const EVENT_DEFAULT_PROVIDERS_START = 'default-providers-start';
|
|
15
11
|
const EVENT_DEFAULT_PROVIDERS_END = 'default-providers-end';
|
|
16
12
|
const DEFAULT_PROVIDERS = [
|
|
@@ -44,11 +40,15 @@ class RepositoryManager {
|
|
|
44
40
|
async stopListening() {
|
|
45
41
|
return this.watcher.unwatch();
|
|
46
42
|
}
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Setting the source of change helps us know
|
|
45
|
+
* how to react to changes in the UI.
|
|
46
|
+
*/
|
|
47
|
+
setSourceOfChangeFor(file, source) {
|
|
48
|
+
return this.watcher.setSourceOfChangeFor(file, source);
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
return this.watcher.
|
|
50
|
+
clearSourceOfChangeFor(file) {
|
|
51
|
+
return this.watcher.clearSourceOfChangeFor(file);
|
|
52
52
|
}
|
|
53
53
|
ensureDefaultProviders() {
|
|
54
54
|
socketManager.emitGlobal(EVENT_DEFAULT_PROVIDERS_START, { providers: DEFAULT_PROVIDERS });
|
|
@@ -79,7 +79,7 @@ class RepositoryManager {
|
|
|
79
79
|
console.error(`Failed to install asset: ${ref}`, e);
|
|
80
80
|
throw e;
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
cacheManager.flush();
|
|
83
83
|
//console.log(`Asset installed: ${ref}`);
|
|
84
84
|
};
|
|
85
85
|
};
|
package/dist/esm/src/types.d.ts
CHANGED
|
@@ -8,6 +8,8 @@ export type StringMap = {
|
|
|
8
8
|
export type AnyMap = {
|
|
9
9
|
[key: string]: any;
|
|
10
10
|
};
|
|
11
|
+
export type SourceOfChange = 'user' | 'filesystem';
|
|
12
|
+
export type WatchEventName = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir';
|
|
11
13
|
export type LogLevel = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG' | 'TRACE' | 'FATAL';
|
|
12
14
|
export type LogSource = 'stdout' | 'stderr';
|
|
13
15
|
export type EnvironmentType = 'docker' | 'process';
|
package/package.json
CHANGED
package/src/RepositoryWatcher.ts
CHANGED
|
@@ -8,13 +8,9 @@ import _ from 'lodash';
|
|
|
8
8
|
import { socketManager } from './socketManager';
|
|
9
9
|
import { definitionsManager } from './definitionsManager';
|
|
10
10
|
import { assetManager } from './assetManager';
|
|
11
|
+
import { SourceOfChange, WatchEventName } from './types';
|
|
12
|
+
import { cacheManager } from './cacheManager';
|
|
11
13
|
|
|
12
|
-
function clearAllCaches() {
|
|
13
|
-
definitionsManager.clearCache();
|
|
14
|
-
assetManager.clearCache();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type WatchEventName = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir';
|
|
18
14
|
interface AssetIdentity {
|
|
19
15
|
handle: string;
|
|
20
16
|
name: string;
|
|
@@ -27,7 +23,7 @@ export class RepositoryWatcher {
|
|
|
27
23
|
private readonly baseDir: string;
|
|
28
24
|
private allDefinitions: DefinitionInfo[] = [];
|
|
29
25
|
private symbolicLinks: { [link: string]: string } = {};
|
|
30
|
-
private
|
|
26
|
+
private sourceOfChange: Map<string, SourceOfChange> = new Map();
|
|
31
27
|
constructor() {
|
|
32
28
|
this.baseDir = ClusterConfiguration.getRepositoryBasedir();
|
|
33
29
|
}
|
|
@@ -66,19 +62,19 @@ export class RepositoryWatcher {
|
|
|
66
62
|
}
|
|
67
63
|
}
|
|
68
64
|
|
|
69
|
-
async
|
|
70
|
-
this.
|
|
65
|
+
async setSourceOfChangeFor(file: string, source: SourceOfChange) {
|
|
66
|
+
this.sourceOfChange.set(file, source);
|
|
71
67
|
const realPath = await FS.realpath(file);
|
|
72
68
|
if (realPath !== file) {
|
|
73
|
-
this.
|
|
69
|
+
this.sourceOfChange.set(realPath, source);
|
|
74
70
|
}
|
|
75
71
|
}
|
|
76
72
|
|
|
77
|
-
async
|
|
78
|
-
this.
|
|
73
|
+
async clearSourceOfChangeFor(file: string) {
|
|
74
|
+
this.sourceOfChange.delete(file);
|
|
79
75
|
const realPath = await FS.realpath(file);
|
|
80
76
|
if (realPath !== file) {
|
|
81
|
-
this.
|
|
77
|
+
this.sourceOfChange.delete(realPath);
|
|
82
78
|
}
|
|
83
79
|
}
|
|
84
80
|
|
|
@@ -139,10 +135,6 @@ export class RepositoryWatcher {
|
|
|
139
135
|
return;
|
|
140
136
|
}
|
|
141
137
|
|
|
142
|
-
if (this.ignoredFiles.has(path)) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
138
|
//console.log('File changed', eventName, path);
|
|
147
139
|
|
|
148
140
|
const assetIdentity = await this.getAssetIdentity(path);
|
|
@@ -172,10 +164,14 @@ export class RepositoryWatcher {
|
|
|
172
164
|
}
|
|
173
165
|
}
|
|
174
166
|
|
|
175
|
-
|
|
167
|
+
const sourceOfChange = this.sourceOfChange.get(path) ?? 'filesystem';
|
|
168
|
+
await this.checkForChange(assetIdentity, sourceOfChange);
|
|
169
|
+
|
|
170
|
+
// We consume the sourceOfChange when the file is changed
|
|
171
|
+
this.sourceOfChange.delete(path);
|
|
176
172
|
}
|
|
177
173
|
|
|
178
|
-
private async checkForChange(assetIdentity: AssetIdentity) {
|
|
174
|
+
private async checkForChange(assetIdentity: AssetIdentity, sourceOfChange: SourceOfChange) {
|
|
179
175
|
const ymlPath = Path.join(
|
|
180
176
|
this.baseDir,
|
|
181
177
|
assetIdentity.handle,
|
|
@@ -219,13 +215,15 @@ export class RepositoryWatcher {
|
|
|
219
215
|
type,
|
|
220
216
|
definition: newDefinition?.definition ?? currentDefinition?.definition,
|
|
221
217
|
asset: assetIdentity,
|
|
218
|
+
sourceOfChange,
|
|
222
219
|
};
|
|
223
220
|
|
|
224
221
|
this.allDefinitions = newDefinitions;
|
|
225
222
|
|
|
226
223
|
//console.log('Asset changed', payload);
|
|
227
224
|
socketManager.emitGlobal('asset-change', payload);
|
|
228
|
-
|
|
225
|
+
|
|
226
|
+
cacheManager.flush();
|
|
229
227
|
}
|
|
230
228
|
|
|
231
229
|
private async exists(path: string): Promise<boolean> {
|