@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
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## [0.16.1](https://github.com/kapetacom/local-cluster-service/compare/v0.16.0...v0.16.1) (2023-08-11)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* Instead of ignoring we set source-of-change ([ecd23c4](https://github.com/kapetacom/local-cluster-service/commit/ecd23c4c3316a189038a1f2f2f2c8794f6153261))
|
7
|
+
|
1
8
|
# [0.16.0](https://github.com/kapetacom/local-cluster-service/compare/v0.15.3...v0.16.0) (2023-08-11)
|
2
9
|
|
3
10
|
|
@@ -1,15 +1,16 @@
|
|
1
|
+
import { SourceOfChange } from './types';
|
1
2
|
export declare class RepositoryWatcher {
|
2
3
|
private watcher?;
|
3
4
|
private disabled;
|
4
5
|
private readonly baseDir;
|
5
6
|
private allDefinitions;
|
6
7
|
private symbolicLinks;
|
7
|
-
private
|
8
|
+
private sourceOfChange;
|
8
9
|
constructor();
|
9
10
|
setDisabled(disabled: boolean): void;
|
10
11
|
watch(): void;
|
11
|
-
|
12
|
-
|
12
|
+
setSourceOfChangeFor(file: string, source: SourceOfChange): Promise<void>;
|
13
|
+
clearSourceOfChangeFor(file: string): Promise<void>;
|
13
14
|
unwatch(): Promise<void>;
|
14
15
|
private getAssetIdentity;
|
15
16
|
private handleFileChange;
|
@@ -12,12 +12,7 @@ const yaml_1 = __importDefault(require("yaml"));
|
|
12
12
|
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
13
13
|
const lodash_1 = __importDefault(require("lodash"));
|
14
14
|
const socketManager_1 = require("./socketManager");
|
15
|
-
const
|
16
|
-
const assetManager_1 = require("./assetManager");
|
17
|
-
function clearAllCaches() {
|
18
|
-
definitionsManager_1.definitionsManager.clearCache();
|
19
|
-
assetManager_1.assetManager.clearCache();
|
20
|
-
}
|
15
|
+
const cacheManager_1 = require("./cacheManager");
|
21
16
|
const KAPETA_YML_RX = /^kapeta.ya?ml$/;
|
22
17
|
class RepositoryWatcher {
|
23
18
|
watcher;
|
@@ -25,7 +20,7 @@ class RepositoryWatcher {
|
|
25
20
|
baseDir;
|
26
21
|
allDefinitions = [];
|
27
22
|
symbolicLinks = {};
|
28
|
-
|
23
|
+
sourceOfChange = new Map();
|
29
24
|
constructor() {
|
30
25
|
this.baseDir = local_cluster_config_1.default.getRepositoryBasedir();
|
31
26
|
}
|
@@ -61,18 +56,18 @@ class RepositoryWatcher {
|
|
61
56
|
return;
|
62
57
|
}
|
63
58
|
}
|
64
|
-
async
|
65
|
-
this.
|
59
|
+
async setSourceOfChangeFor(file, source) {
|
60
|
+
this.sourceOfChange.set(file, source);
|
66
61
|
const realPath = await fs_extra_1.default.realpath(file);
|
67
62
|
if (realPath !== file) {
|
68
|
-
this.
|
63
|
+
this.sourceOfChange.set(realPath, source);
|
69
64
|
}
|
70
65
|
}
|
71
|
-
async
|
72
|
-
this.
|
66
|
+
async clearSourceOfChangeFor(file) {
|
67
|
+
this.sourceOfChange.delete(file);
|
73
68
|
const realPath = await fs_extra_1.default.realpath(file);
|
74
69
|
if (realPath !== file) {
|
75
|
-
this.
|
70
|
+
this.sourceOfChange.delete(realPath);
|
76
71
|
}
|
77
72
|
}
|
78
73
|
async unwatch() {
|
@@ -127,9 +122,6 @@ class RepositoryWatcher {
|
|
127
122
|
if (!path) {
|
128
123
|
return;
|
129
124
|
}
|
130
|
-
if (this.ignoredFiles.has(path)) {
|
131
|
-
return;
|
132
|
-
}
|
133
125
|
//console.log('File changed', eventName, path);
|
134
126
|
const assetIdentity = await this.getAssetIdentity(path);
|
135
127
|
if (!assetIdentity) {
|
@@ -153,9 +145,12 @@ class RepositoryWatcher {
|
|
153
145
|
await this.updateSymlinkTarget(path);
|
154
146
|
}
|
155
147
|
}
|
156
|
-
|
148
|
+
const sourceOfChange = this.sourceOfChange.get(path) ?? 'filesystem';
|
149
|
+
await this.checkForChange(assetIdentity, sourceOfChange);
|
150
|
+
// We consume the sourceOfChange when the file is changed
|
151
|
+
this.sourceOfChange.delete(path);
|
157
152
|
}
|
158
|
-
async checkForChange(assetIdentity) {
|
153
|
+
async checkForChange(assetIdentity, sourceOfChange) {
|
159
154
|
const ymlPath = node_path_1.default.join(this.baseDir, assetIdentity.handle, assetIdentity.name, assetIdentity.version, 'kapeta.yml');
|
160
155
|
const newDefinitions = local_cluster_config_1.default.getDefinitions();
|
161
156
|
const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
|
@@ -194,11 +189,12 @@ class RepositoryWatcher {
|
|
194
189
|
type,
|
195
190
|
definition: newDefinition?.definition ?? currentDefinition?.definition,
|
196
191
|
asset: assetIdentity,
|
192
|
+
sourceOfChange,
|
197
193
|
};
|
198
194
|
this.allDefinitions = newDefinitions;
|
199
195
|
//console.log('Asset changed', payload);
|
200
196
|
socketManager_1.socketManager.emitGlobal('asset-change', payload);
|
201
|
-
|
197
|
+
cacheManager_1.cacheManager.flush();
|
202
198
|
}
|
203
199
|
async exists(path) {
|
204
200
|
try {
|
@@ -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 {};
|
@@ -7,7 +7,6 @@ exports.assetManager = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
8
8
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
9
9
|
const yaml_1 = __importDefault(require("yaml"));
|
10
|
-
const node_cache_1 = __importDefault(require("node-cache"));
|
11
10
|
const codeGeneratorManager_1 = require("./codeGeneratorManager");
|
12
11
|
const progressListener_1 = require("./progressListener");
|
13
12
|
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
@@ -16,10 +15,8 @@ const nodejs_registry_utils_1 = require("@kapeta/nodejs-registry-utils");
|
|
16
15
|
const definitionsManager_1 = require("./definitionsManager");
|
17
16
|
const utils_1 = require("./utils/utils");
|
18
17
|
const taskManager_1 = require("./taskManager");
|
19
|
-
|
20
|
-
|
21
|
-
exports.assetManager.clearCache();
|
22
|
-
}
|
18
|
+
const cacheManager_1 = require("./cacheManager");
|
19
|
+
const CACHE_TTL = 60 * 60 * 1000; // 1 hour
|
23
20
|
function enrichAsset(asset) {
|
24
21
|
return {
|
25
22
|
ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
|
@@ -45,15 +42,6 @@ function parseRef(ref) {
|
|
45
42
|
return [out[0].toLowerCase(), out[1].toLowerCase()];
|
46
43
|
}
|
47
44
|
class AssetManager {
|
48
|
-
cache;
|
49
|
-
constructor() {
|
50
|
-
this.cache = new node_cache_1.default({
|
51
|
-
stdTTL: 60 * 60, // 1 hour
|
52
|
-
});
|
53
|
-
}
|
54
|
-
clearCache() {
|
55
|
-
this.cache.flushAll();
|
56
|
-
}
|
57
45
|
/**
|
58
46
|
*
|
59
47
|
* @param {string[]} [assetKinds]
|
@@ -86,8 +74,8 @@ class AssetManager {
|
|
86
74
|
async getAsset(ref, noCache = false, autoFetch = true) {
|
87
75
|
ref = (0, utils_1.normalizeKapetaUri)(ref);
|
88
76
|
const cacheKey = `getAsset:${ref}`;
|
89
|
-
if (!noCache &&
|
90
|
-
return
|
77
|
+
if (!noCache && cacheManager_1.cacheManager.has(cacheKey)) {
|
78
|
+
return cacheManager_1.cacheManager.get(cacheKey);
|
91
79
|
}
|
92
80
|
const uri = (0, nodejs_utils_1.parseKapetaUri)(ref);
|
93
81
|
if (autoFetch) {
|
@@ -101,11 +89,11 @@ class AssetManager {
|
|
101
89
|
throw new Error('Asset not found: ' + ref);
|
102
90
|
}
|
103
91
|
if (asset) {
|
104
|
-
|
92
|
+
cacheManager_1.cacheManager.set(cacheKey, asset, CACHE_TTL);
|
105
93
|
}
|
106
94
|
return asset;
|
107
95
|
}
|
108
|
-
async createAsset(path, yaml) {
|
96
|
+
async createAsset(path, yaml, sourceOfChange = 'filesystem') {
|
109
97
|
if (await fs_extra_1.default.pathExists(path)) {
|
110
98
|
throw new Error('File already exists: ' + path);
|
111
99
|
}
|
@@ -113,14 +101,15 @@ class AssetManager {
|
|
113
101
|
if (!(await fs_extra_1.default.pathExists(dirName))) {
|
114
102
|
await fs_extra_1.default.mkdirp(dirName);
|
115
103
|
}
|
104
|
+
await repositoryManager_1.repositoryManager.setSourceOfChangeFor(path, sourceOfChange);
|
116
105
|
await fs_extra_1.default.writeFile(path, yaml_1.default.stringify(yaml));
|
117
106
|
const asset = await this.importFile(path);
|
118
|
-
|
107
|
+
cacheManager_1.cacheManager.flush();
|
119
108
|
const ref = `kapeta://${yaml.metadata.name}:local`;
|
120
109
|
this.maybeGenerateCode(ref, path, yaml);
|
121
110
|
return asset;
|
122
111
|
}
|
123
|
-
async updateAsset(ref, yaml) {
|
112
|
+
async updateAsset(ref, yaml, sourceOfChange = 'filesystem') {
|
124
113
|
const asset = await this.getAsset(ref, true, false);
|
125
114
|
if (!asset) {
|
126
115
|
throw new Error('Attempted to update unknown asset: ' + ref);
|
@@ -131,36 +120,11 @@ class AssetManager {
|
|
131
120
|
if (!asset.ymlPath) {
|
132
121
|
throw new Error('Attempted to update corrupted asset: ' + ref);
|
133
122
|
}
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
clearAllCaches();
|
140
|
-
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
141
|
-
}
|
142
|
-
finally {
|
143
|
-
//We need to wait a bit for the disk to settle before we can resume watching
|
144
|
-
setTimeout(async () => {
|
145
|
-
try {
|
146
|
-
await repositoryManager_1.repositoryManager.resumeChangedFor(path);
|
147
|
-
}
|
148
|
-
catch (e) { }
|
149
|
-
}, 500);
|
150
|
-
}
|
151
|
-
}
|
152
|
-
maybeGenerateCode(ref, ymlPath, block) {
|
153
|
-
ref = (0, utils_1.normalizeKapetaUri)(ref);
|
154
|
-
if (codeGeneratorManager_1.codeGeneratorManager.canGenerateCode(block)) {
|
155
|
-
const assetTitle = block.metadata.title ? block.metadata.title : (0, nodejs_utils_1.parseKapetaUri)(block.metadata.name).name;
|
156
|
-
taskManager_1.taskManager.add(`codegen:${ref}`, async () => {
|
157
|
-
await codeGeneratorManager_1.codeGeneratorManager.generate(ymlPath, block);
|
158
|
-
}, {
|
159
|
-
name: `Generating code for ${assetTitle}`,
|
160
|
-
});
|
161
|
-
return true;
|
162
|
-
}
|
163
|
-
return false;
|
123
|
+
await repositoryManager_1.repositoryManager.setSourceOfChangeFor(asset.ymlPath, sourceOfChange);
|
124
|
+
await fs_extra_1.default.writeFile(asset.ymlPath, yaml_1.default.stringify(yaml));
|
125
|
+
console.log('Wrote to ' + asset.ymlPath);
|
126
|
+
cacheManager_1.cacheManager.flush();
|
127
|
+
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
164
128
|
}
|
165
129
|
async importFile(filePath) {
|
166
130
|
if (filePath.startsWith('file://')) {
|
@@ -174,7 +138,7 @@ class AssetManager {
|
|
174
138
|
await nodejs_registry_utils_1.Actions.link(new progressListener_1.ProgressListener(), node_path_1.default.dirname(filePath));
|
175
139
|
const version = 'local';
|
176
140
|
const refs = assetInfos.map((assetInfo) => `kapeta://${assetInfo.metadata.name}:${version}`);
|
177
|
-
|
141
|
+
cacheManager_1.cacheManager.flush();
|
178
142
|
return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
|
179
143
|
}
|
180
144
|
async unregisterAsset(ref) {
|
@@ -182,7 +146,7 @@ class AssetManager {
|
|
182
146
|
if (!asset) {
|
183
147
|
throw new Error('Asset does not exists: ' + ref);
|
184
148
|
}
|
185
|
-
|
149
|
+
cacheManager_1.cacheManager.flush();
|
186
150
|
await nodejs_registry_utils_1.Actions.uninstall(new progressListener_1.ProgressListener(), [asset.ref]);
|
187
151
|
}
|
188
152
|
async installAsset(ref) {
|
@@ -194,5 +158,18 @@ class AssetManager {
|
|
194
158
|
console.log('Installing %s', ref);
|
195
159
|
return await repositoryManager_1.repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, false);
|
196
160
|
}
|
161
|
+
maybeGenerateCode(ref, ymlPath, block) {
|
162
|
+
ref = (0, utils_1.normalizeKapetaUri)(ref);
|
163
|
+
if (codeGeneratorManager_1.codeGeneratorManager.canGenerateCode(block)) {
|
164
|
+
const assetTitle = block.metadata.title ? block.metadata.title : (0, nodejs_utils_1.parseKapetaUri)(block.metadata.name).name;
|
165
|
+
taskManager_1.taskManager.add(`codegen:${ref}`, async () => {
|
166
|
+
await codeGeneratorManager_1.codeGeneratorManager.generate(ymlPath, block);
|
167
|
+
}, {
|
168
|
+
name: `Generating code for ${assetTitle}`,
|
169
|
+
});
|
170
|
+
return true;
|
171
|
+
}
|
172
|
+
return false;
|
173
|
+
}
|
197
174
|
}
|
198
175
|
exports.assetManager = new AssetManager();
|
@@ -63,7 +63,7 @@ router.post('/create', async (req, res) => {
|
|
63
63
|
}
|
64
64
|
const content = parseBody(req);
|
65
65
|
try {
|
66
|
-
const assets = await assetManager_1.assetManager.createAsset(req.query.path, content);
|
66
|
+
const assets = await assetManager_1.assetManager.createAsset(req.query.path, content, 'user');
|
67
67
|
res.status(200).send(assets);
|
68
68
|
}
|
69
69
|
catch (err) {
|
@@ -81,7 +81,7 @@ router.put('/update', async (req, res) => {
|
|
81
81
|
}
|
82
82
|
const content = parseBody(req);
|
83
83
|
try {
|
84
|
-
await assetManager_1.assetManager.updateAsset(req.query.ref, content);
|
84
|
+
await assetManager_1.assetManager.updateAsset(req.query.ref, content, 'user');
|
85
85
|
res.sendStatus(204);
|
86
86
|
}
|
87
87
|
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,38 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.doCached = exports.cacheManager = void 0;
|
7
|
+
const node_cache_1 = __importDefault(require("node-cache"));
|
8
|
+
const DEFAULT_CACHE_TTL = 60 * 1000; // 1 min
|
9
|
+
class CacheManager {
|
10
|
+
cache = new node_cache_1.default();
|
11
|
+
flush() {
|
12
|
+
this.cache.flushAll();
|
13
|
+
}
|
14
|
+
doCached(key, getter, ttl = DEFAULT_CACHE_TTL) {
|
15
|
+
const data = this.cache.get(key);
|
16
|
+
if (data !== undefined) {
|
17
|
+
return data;
|
18
|
+
}
|
19
|
+
const result = getter();
|
20
|
+
this.cache.set(key, result, ttl);
|
21
|
+
return result;
|
22
|
+
}
|
23
|
+
get(key) {
|
24
|
+
return this.cache.get(key);
|
25
|
+
}
|
26
|
+
set(key, data, ttl = DEFAULT_CACHE_TTL) {
|
27
|
+
this.cache.set(key, data, ttl);
|
28
|
+
}
|
29
|
+
has(key) {
|
30
|
+
return this.cache.has(key);
|
31
|
+
}
|
32
|
+
remove(key) {
|
33
|
+
return this.cache.del(key);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
exports.cacheManager = new CacheManager();
|
37
|
+
const doCached = (key, getter, ttl = DEFAULT_CACHE_TTL) => exports.cacheManager.doCached(key, getter, ttl);
|
38
|
+
exports.doCached = doCached;
|
@@ -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[];
|
@@ -6,10 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.definitionsManager = void 0;
|
7
7
|
const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-config"));
|
8
8
|
const nodejs_utils_1 = require("@kapeta/nodejs-utils");
|
9
|
-
const
|
9
|
+
const cacheManager_1 = require("./cacheManager");
|
10
10
|
class DefinitionsManager {
|
11
|
-
|
12
|
-
getKey(kindFilter) {
|
11
|
+
getHash(kindFilter) {
|
13
12
|
if (kindFilter) {
|
14
13
|
if (Array.isArray(kindFilter)) {
|
15
14
|
return kindFilter.join(',');
|
@@ -18,31 +17,18 @@ class DefinitionsManager {
|
|
18
17
|
}
|
19
18
|
return 'none';
|
20
19
|
}
|
21
|
-
|
22
|
-
this.
|
23
|
-
}
|
24
|
-
doCached(key, getter) {
|
25
|
-
if (this.cache[key]) {
|
26
|
-
if (this.cache[key].expires > Date.now()) {
|
27
|
-
return this.cache[key].definitions;
|
28
|
-
}
|
29
|
-
delete this.cache[key];
|
30
|
-
}
|
31
|
-
this.cache[key] = {
|
32
|
-
expires: Date.now() + CACHE_TTL,
|
33
|
-
definitions: getter(),
|
34
|
-
};
|
35
|
-
return this.cache[key].definitions;
|
20
|
+
getFullKey(kindFilter) {
|
21
|
+
return `DefinitionsManager:${this.getHash(kindFilter)}`;
|
36
22
|
}
|
37
23
|
getDefinitions(kindFilter) {
|
38
|
-
const key = this.
|
39
|
-
return
|
24
|
+
const key = this.getFullKey(kindFilter);
|
25
|
+
return (0, cacheManager_1.doCached)(key, () => local_cluster_config_1.default.getDefinitions(kindFilter));
|
40
26
|
}
|
41
27
|
exists(ref) {
|
42
28
|
return !!this.getDefinition(ref);
|
43
29
|
}
|
44
30
|
getProviderDefinitions() {
|
45
|
-
return
|
31
|
+
return (0, cacheManager_1.doCached)('providers', () => local_cluster_config_1.default.getProviderDefinitions());
|
46
32
|
}
|
47
33
|
getDefinition(ref) {
|
48
34
|
const uri = (0, nodejs_utils_1.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[]>;
|
@@ -12,11 +12,7 @@ const taskManager_1 = require("./taskManager");
|
|
12
12
|
const utils_1 = require("./utils/utils");
|
13
13
|
const progressListener_1 = require("./progressListener");
|
14
14
|
const RepositoryWatcher_1 = require("./RepositoryWatcher");
|
15
|
-
const
|
16
|
-
function clearAllCaches() {
|
17
|
-
definitionsManager_1.definitionsManager.clearCache();
|
18
|
-
assetManager_1.assetManager.clearCache();
|
19
|
-
}
|
15
|
+
const cacheManager_1 = require("./cacheManager");
|
20
16
|
const EVENT_DEFAULT_PROVIDERS_START = 'default-providers-start';
|
21
17
|
const EVENT_DEFAULT_PROVIDERS_END = 'default-providers-end';
|
22
18
|
const DEFAULT_PROVIDERS = [
|
@@ -50,11 +46,15 @@ class RepositoryManager {
|
|
50
46
|
async stopListening() {
|
51
47
|
return this.watcher.unwatch();
|
52
48
|
}
|
53
|
-
|
54
|
-
|
49
|
+
/**
|
50
|
+
* Setting the source of change helps us know
|
51
|
+
* how to react to changes in the UI.
|
52
|
+
*/
|
53
|
+
setSourceOfChangeFor(file, source) {
|
54
|
+
return this.watcher.setSourceOfChangeFor(file, source);
|
55
55
|
}
|
56
|
-
|
57
|
-
return this.watcher.
|
56
|
+
clearSourceOfChangeFor(file) {
|
57
|
+
return this.watcher.clearSourceOfChangeFor(file);
|
58
58
|
}
|
59
59
|
ensureDefaultProviders() {
|
60
60
|
socketManager_1.socketManager.emitGlobal(EVENT_DEFAULT_PROVIDERS_START, { providers: DEFAULT_PROVIDERS });
|
@@ -85,7 +85,7 @@ class RepositoryManager {
|
|
85
85
|
console.error(`Failed to install asset: ${ref}`, e);
|
86
86
|
throw e;
|
87
87
|
}
|
88
|
-
|
88
|
+
cacheManager_1.cacheManager.flush();
|
89
89
|
//console.log(`Asset installed: ${ref}`);
|
90
90
|
};
|
91
91
|
};
|
package/dist/cjs/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';
|
@@ -1,15 +1,16 @@
|
|
1
|
+
import { SourceOfChange } from './types';
|
1
2
|
export declare class RepositoryWatcher {
|
2
3
|
private watcher?;
|
3
4
|
private disabled;
|
4
5
|
private readonly baseDir;
|
5
6
|
private allDefinitions;
|
6
7
|
private symbolicLinks;
|
7
|
-
private
|
8
|
+
private sourceOfChange;
|
8
9
|
constructor();
|
9
10
|
setDisabled(disabled: boolean): void;
|
10
11
|
watch(): void;
|
11
|
-
|
12
|
-
|
12
|
+
setSourceOfChangeFor(file: string, source: SourceOfChange): Promise<void>;
|
13
|
+
clearSourceOfChangeFor(file: string): Promise<void>;
|
13
14
|
unwatch(): Promise<void>;
|
14
15
|
private getAssetIdentity;
|
15
16
|
private handleFileChange;
|
@@ -6,12 +6,7 @@ import YAML from 'yaml';
|
|
6
6
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
7
7
|
import _ from 'lodash';
|
8
8
|
import { socketManager } from './socketManager';
|
9
|
-
import {
|
10
|
-
import { assetManager } from './assetManager';
|
11
|
-
function clearAllCaches() {
|
12
|
-
definitionsManager.clearCache();
|
13
|
-
assetManager.clearCache();
|
14
|
-
}
|
9
|
+
import { cacheManager } from './cacheManager';
|
15
10
|
const KAPETA_YML_RX = /^kapeta.ya?ml$/;
|
16
11
|
export class RepositoryWatcher {
|
17
12
|
watcher;
|
@@ -19,7 +14,7 @@ export class RepositoryWatcher {
|
|
19
14
|
baseDir;
|
20
15
|
allDefinitions = [];
|
21
16
|
symbolicLinks = {};
|
22
|
-
|
17
|
+
sourceOfChange = new Map();
|
23
18
|
constructor() {
|
24
19
|
this.baseDir = ClusterConfiguration.getRepositoryBasedir();
|
25
20
|
}
|
@@ -55,18 +50,18 @@ export class RepositoryWatcher {
|
|
55
50
|
return;
|
56
51
|
}
|
57
52
|
}
|
58
|
-
async
|
59
|
-
this.
|
53
|
+
async setSourceOfChangeFor(file, source) {
|
54
|
+
this.sourceOfChange.set(file, source);
|
60
55
|
const realPath = await FS.realpath(file);
|
61
56
|
if (realPath !== file) {
|
62
|
-
this.
|
57
|
+
this.sourceOfChange.set(realPath, source);
|
63
58
|
}
|
64
59
|
}
|
65
|
-
async
|
66
|
-
this.
|
60
|
+
async clearSourceOfChangeFor(file) {
|
61
|
+
this.sourceOfChange.delete(file);
|
67
62
|
const realPath = await FS.realpath(file);
|
68
63
|
if (realPath !== file) {
|
69
|
-
this.
|
64
|
+
this.sourceOfChange.delete(realPath);
|
70
65
|
}
|
71
66
|
}
|
72
67
|
async unwatch() {
|
@@ -121,9 +116,6 @@ export class RepositoryWatcher {
|
|
121
116
|
if (!path) {
|
122
117
|
return;
|
123
118
|
}
|
124
|
-
if (this.ignoredFiles.has(path)) {
|
125
|
-
return;
|
126
|
-
}
|
127
119
|
//console.log('File changed', eventName, path);
|
128
120
|
const assetIdentity = await this.getAssetIdentity(path);
|
129
121
|
if (!assetIdentity) {
|
@@ -147,9 +139,12 @@ export class RepositoryWatcher {
|
|
147
139
|
await this.updateSymlinkTarget(path);
|
148
140
|
}
|
149
141
|
}
|
150
|
-
|
142
|
+
const sourceOfChange = this.sourceOfChange.get(path) ?? 'filesystem';
|
143
|
+
await this.checkForChange(assetIdentity, sourceOfChange);
|
144
|
+
// We consume the sourceOfChange when the file is changed
|
145
|
+
this.sourceOfChange.delete(path);
|
151
146
|
}
|
152
|
-
async checkForChange(assetIdentity) {
|
147
|
+
async checkForChange(assetIdentity, sourceOfChange) {
|
153
148
|
const ymlPath = Path.join(this.baseDir, assetIdentity.handle, assetIdentity.name, assetIdentity.version, 'kapeta.yml');
|
154
149
|
const newDefinitions = ClusterConfiguration.getDefinitions();
|
155
150
|
const newDefinition = newDefinitions.find((d) => d.ymlPath === ymlPath);
|
@@ -188,11 +183,12 @@ export class RepositoryWatcher {
|
|
188
183
|
type,
|
189
184
|
definition: newDefinition?.definition ?? currentDefinition?.definition,
|
190
185
|
asset: assetIdentity,
|
186
|
+
sourceOfChange,
|
191
187
|
};
|
192
188
|
this.allDefinitions = newDefinitions;
|
193
189
|
//console.log('Asset changed', payload);
|
194
190
|
socketManager.emitGlobal('asset-change', payload);
|
195
|
-
|
191
|
+
cacheManager.flush();
|
196
192
|
}
|
197
193
|
async exists(path) {
|
198
194
|
try {
|