@kapeta/local-cluster-service 0.16.1 → 0.16.3
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 +14 -0
- package/dist/cjs/src/RepositoryWatcher.js +16 -6
- package/dist/cjs/src/assetManager.js +25 -7
- package/dist/cjs/src/cacheManager.d.ts +2 -2
- package/dist/cjs/src/cacheManager.js +10 -1
- package/dist/cjs/src/definitionsManager.d.ts +1 -0
- package/dist/cjs/src/definitionsManager.js +4 -1
- package/dist/cjs/src/instances/routes.js +6 -0
- package/dist/esm/src/RepositoryWatcher.js +16 -6
- package/dist/esm/src/assetManager.js +25 -7
- package/dist/esm/src/cacheManager.d.ts +2 -2
- package/dist/esm/src/cacheManager.js +9 -1
- package/dist/esm/src/definitionsManager.d.ts +1 -0
- package/dist/esm/src/definitionsManager.js +5 -2
- package/dist/esm/src/instances/routes.js +6 -0
- package/package.json +1 -1
- package/src/RepositoryWatcher.ts +14 -8
- package/src/assetManager.ts +28 -7
- package/src/cacheManager.ts +10 -1
- package/src/definitionsManager.ts +6 -2
- package/src/instances/routes.ts +7 -0
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## [0.16.3](https://github.com/kapetacom/local-cluster-service/compare/v0.16.2...v0.16.3) (2023-08-14)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* Add route for getting status for a single instance ([00159e2](https://github.com/kapetacom/local-cluster-service/commit/00159e255015b519d741c6528a6c9ed3a586dc25))
|
7
|
+
|
8
|
+
## [0.16.2](https://github.com/kapetacom/local-cluster-service/compare/v0.16.1...v0.16.2) (2023-08-12)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* Be smarter about caching ([086ffe4](https://github.com/kapetacom/local-cluster-service/commit/086ffe416a044a8d9dc5e33aa879960d3e3c2b1a))
|
14
|
+
|
1
15
|
## [0.16.1](https://github.com/kapetacom/local-cluster-service/compare/v0.16.0...v0.16.1) (2023-08-11)
|
2
16
|
|
3
17
|
|
@@ -58,16 +58,26 @@ class RepositoryWatcher {
|
|
58
58
|
}
|
59
59
|
async setSourceOfChangeFor(file, source) {
|
60
60
|
this.sourceOfChange.set(file, source);
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
try {
|
62
|
+
const realPath = await fs_extra_1.default.realpath(file);
|
63
|
+
if (realPath !== file) {
|
64
|
+
this.sourceOfChange.set(realPath, source);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
catch (e) {
|
68
|
+
// Ignore
|
64
69
|
}
|
65
70
|
}
|
66
71
|
async clearSourceOfChangeFor(file) {
|
67
72
|
this.sourceOfChange.delete(file);
|
68
|
-
|
69
|
-
|
70
|
-
|
73
|
+
try {
|
74
|
+
const realPath = await fs_extra_1.default.realpath(file);
|
75
|
+
if (realPath !== file) {
|
76
|
+
this.sourceOfChange.delete(realPath);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
catch (e) {
|
80
|
+
// Ignore
|
71
81
|
}
|
72
82
|
}
|
73
83
|
async unwatch() {
|
@@ -17,6 +17,7 @@ const utils_1 = require("./utils/utils");
|
|
17
17
|
const taskManager_1 = require("./taskManager");
|
18
18
|
const cacheManager_1 = require("./cacheManager");
|
19
19
|
const CACHE_TTL = 60 * 60 * 1000; // 1 hour
|
20
|
+
const toKey = (ref) => `assetManager:asset:${ref}`;
|
20
21
|
function enrichAsset(asset) {
|
21
22
|
return {
|
22
23
|
ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
|
@@ -73,7 +74,7 @@ class AssetManager {
|
|
73
74
|
}
|
74
75
|
async getAsset(ref, noCache = false, autoFetch = true) {
|
75
76
|
ref = (0, utils_1.normalizeKapetaUri)(ref);
|
76
|
-
const cacheKey =
|
77
|
+
const cacheKey = toKey(ref);
|
77
78
|
if (!noCache && cacheManager_1.cacheManager.has(cacheKey)) {
|
78
79
|
return cacheManager_1.cacheManager.get(cacheKey);
|
79
80
|
}
|
@@ -104,12 +105,19 @@ class AssetManager {
|
|
104
105
|
await repositoryManager_1.repositoryManager.setSourceOfChangeFor(path, sourceOfChange);
|
105
106
|
await fs_extra_1.default.writeFile(path, yaml_1.default.stringify(yaml));
|
106
107
|
const asset = await this.importFile(path);
|
107
|
-
|
108
|
+
asset.forEach((a) => {
|
109
|
+
const ref = (0, utils_1.normalizeKapetaUri)(a.ref);
|
110
|
+
const key = toKey(ref);
|
111
|
+
cacheManager_1.cacheManager.set(key, a, CACHE_TTL);
|
112
|
+
});
|
113
|
+
definitionsManager_1.definitionsManager.clearCache();
|
114
|
+
console.log(`Created asset at: ${path}`);
|
108
115
|
const ref = `kapeta://${yaml.metadata.name}:local`;
|
109
116
|
this.maybeGenerateCode(ref, path, yaml);
|
110
117
|
return asset;
|
111
118
|
}
|
112
119
|
async updateAsset(ref, yaml, sourceOfChange = 'filesystem') {
|
120
|
+
ref = (0, utils_1.normalizeKapetaUri)(ref);
|
113
121
|
const asset = await this.getAsset(ref, true, false);
|
114
122
|
if (!asset) {
|
115
123
|
throw new Error('Attempted to update unknown asset: ' + ref);
|
@@ -122,8 +130,9 @@ class AssetManager {
|
|
122
130
|
}
|
123
131
|
await repositoryManager_1.repositoryManager.setSourceOfChangeFor(asset.ymlPath, sourceOfChange);
|
124
132
|
await fs_extra_1.default.writeFile(asset.ymlPath, yaml_1.default.stringify(yaml));
|
125
|
-
console.log(
|
126
|
-
cacheManager_1.cacheManager.
|
133
|
+
console.log(`Updated asset at: ${asset.ymlPath}`);
|
134
|
+
cacheManager_1.cacheManager.remove(toKey(ref));
|
135
|
+
definitionsManager_1.definitionsManager.clearCache();
|
127
136
|
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
128
137
|
}
|
129
138
|
async importFile(filePath) {
|
@@ -137,8 +146,12 @@ class AssetManager {
|
|
137
146
|
const assetInfos = yaml_1.default.parseAllDocuments(content.toString()).map((doc) => doc.toJSON());
|
138
147
|
await nodejs_registry_utils_1.Actions.link(new progressListener_1.ProgressListener(), node_path_1.default.dirname(filePath));
|
139
148
|
const version = 'local';
|
140
|
-
const refs = assetInfos.map((assetInfo) => `kapeta://${assetInfo.metadata.name}:${version}`);
|
141
|
-
|
149
|
+
const refs = assetInfos.map((assetInfo) => (0, utils_1.normalizeKapetaUri)(`kapeta://${assetInfo.metadata.name}:${version}`));
|
150
|
+
refs.forEach((ref) => {
|
151
|
+
const key = toKey(ref);
|
152
|
+
cacheManager_1.cacheManager.remove(key);
|
153
|
+
});
|
154
|
+
definitionsManager_1.definitionsManager.clearCache();
|
142
155
|
return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
|
143
156
|
}
|
144
157
|
async unregisterAsset(ref) {
|
@@ -146,7 +159,9 @@ class AssetManager {
|
|
146
159
|
if (!asset) {
|
147
160
|
throw new Error('Asset does not exists: ' + ref);
|
148
161
|
}
|
149
|
-
|
162
|
+
const key = toKey(ref);
|
163
|
+
cacheManager_1.cacheManager.remove(key);
|
164
|
+
definitionsManager_1.definitionsManager.clearCache();
|
150
165
|
await nodejs_registry_utils_1.Actions.uninstall(new progressListener_1.ProgressListener(), [asset.ref]);
|
151
166
|
}
|
152
167
|
async installAsset(ref) {
|
@@ -156,6 +171,9 @@ class AssetManager {
|
|
156
171
|
}
|
157
172
|
const uri = (0, nodejs_utils_1.parseKapetaUri)(ref);
|
158
173
|
console.log('Installing %s', ref);
|
174
|
+
const key = toKey(ref);
|
175
|
+
cacheManager_1.cacheManager.remove(key);
|
176
|
+
definitionsManager_1.definitionsManager.clearCache();
|
159
177
|
return await repositoryManager_1.repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, false);
|
160
178
|
}
|
161
179
|
maybeGenerateCode(ref, ymlPath, block) {
|
@@ -2,7 +2,7 @@ export interface CacheEntry<T = any> {
|
|
2
2
|
expires: number;
|
3
3
|
data: T;
|
4
4
|
}
|
5
|
-
declare class CacheManager {
|
5
|
+
export declare class CacheManager {
|
6
6
|
private cache;
|
7
7
|
flush(): void;
|
8
8
|
doCached<T>(key: string, getter: () => T, ttl?: number): T;
|
@@ -10,7 +10,7 @@ declare class CacheManager {
|
|
10
10
|
set<T>(key: string, data: T, ttl?: number): void;
|
11
11
|
has(key: string): boolean;
|
12
12
|
remove(key: string): number;
|
13
|
+
removePrefix(key: string): void;
|
13
14
|
}
|
14
15
|
export declare const cacheManager: CacheManager;
|
15
16
|
export declare const doCached: <T>(key: string, getter: () => T, ttl?: number) => T;
|
16
|
-
export {};
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.doCached = exports.cacheManager = void 0;
|
6
|
+
exports.doCached = exports.cacheManager = exports.CacheManager = void 0;
|
7
7
|
const node_cache_1 = __importDefault(require("node-cache"));
|
8
8
|
const DEFAULT_CACHE_TTL = 60 * 1000; // 1 min
|
9
9
|
class CacheManager {
|
@@ -32,7 +32,16 @@ class CacheManager {
|
|
32
32
|
remove(key) {
|
33
33
|
return this.cache.del(key);
|
34
34
|
}
|
35
|
+
removePrefix(key) {
|
36
|
+
const keys = this.cache.keys();
|
37
|
+
for (const k of keys) {
|
38
|
+
if (k.startsWith(key)) {
|
39
|
+
this.remove(k);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
35
43
|
}
|
44
|
+
exports.CacheManager = CacheManager;
|
36
45
|
exports.cacheManager = new CacheManager();
|
37
46
|
const doCached = (key, getter, ttl = DEFAULT_CACHE_TTL) => exports.cacheManager.doCached(key, getter, ttl);
|
38
47
|
exports.doCached = doCached;
|
@@ -6,6 +6,7 @@ declare class DefinitionsManager {
|
|
6
6
|
exists(ref: string): boolean;
|
7
7
|
getProviderDefinitions(): DefinitionInfo[];
|
8
8
|
getDefinition(ref: string): DefinitionInfo | undefined;
|
9
|
+
clearCache(): void;
|
9
10
|
}
|
10
11
|
export declare const definitionsManager: DefinitionsManager;
|
11
12
|
export {};
|
@@ -18,7 +18,7 @@ class DefinitionsManager {
|
|
18
18
|
return 'none';
|
19
19
|
}
|
20
20
|
getFullKey(kindFilter) {
|
21
|
-
return `
|
21
|
+
return `definitionsManager:${this.getHash(kindFilter)}`;
|
22
22
|
}
|
23
23
|
getDefinitions(kindFilter) {
|
24
24
|
const key = this.getFullKey(kindFilter);
|
@@ -39,5 +39,8 @@ class DefinitionsManager {
|
|
39
39
|
return (0, nodejs_utils_1.parseKapetaUri)(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
|
40
40
|
});
|
41
41
|
}
|
42
|
+
clearCache() {
|
43
|
+
cacheManager_1.cacheManager.removePrefix('definitionsManager:');
|
44
|
+
}
|
42
45
|
}
|
43
46
|
exports.definitionsManager = new DefinitionsManager();
|
@@ -26,6 +26,12 @@ router.get('/', (req, res) => {
|
|
26
26
|
router.get('/:systemId/instances', (req, res) => {
|
27
27
|
res.send(instanceManager_1.instanceManager.getInstancesForPlan(req.params.systemId));
|
28
28
|
});
|
29
|
+
/**
|
30
|
+
* Get single instance in a plan
|
31
|
+
*/
|
32
|
+
router.get('/:systemId/instances/:instanceId', (req, res) => {
|
33
|
+
res.send(instanceManager_1.instanceManager.getInstance(req.params.systemId, req.params.instanceId));
|
34
|
+
});
|
29
35
|
/**
|
30
36
|
* Start all instances in a plan
|
31
37
|
*/
|
@@ -52,16 +52,26 @@ export class RepositoryWatcher {
|
|
52
52
|
}
|
53
53
|
async setSourceOfChangeFor(file, source) {
|
54
54
|
this.sourceOfChange.set(file, source);
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
try {
|
56
|
+
const realPath = await FS.realpath(file);
|
57
|
+
if (realPath !== file) {
|
58
|
+
this.sourceOfChange.set(realPath, source);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
catch (e) {
|
62
|
+
// Ignore
|
58
63
|
}
|
59
64
|
}
|
60
65
|
async clearSourceOfChangeFor(file) {
|
61
66
|
this.sourceOfChange.delete(file);
|
62
|
-
|
63
|
-
|
64
|
-
|
67
|
+
try {
|
68
|
+
const realPath = await FS.realpath(file);
|
69
|
+
if (realPath !== file) {
|
70
|
+
this.sourceOfChange.delete(realPath);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
catch (e) {
|
74
|
+
// Ignore
|
65
75
|
}
|
66
76
|
}
|
67
77
|
async unwatch() {
|
@@ -11,6 +11,7 @@ import { normalizeKapetaUri } from './utils/utils';
|
|
11
11
|
import { taskManager } from './taskManager';
|
12
12
|
import { cacheManager } from './cacheManager';
|
13
13
|
const CACHE_TTL = 60 * 60 * 1000; // 1 hour
|
14
|
+
const toKey = (ref) => `assetManager:asset:${ref}`;
|
14
15
|
function enrichAsset(asset) {
|
15
16
|
return {
|
16
17
|
ref: `kapeta://${asset.definition.metadata.name}:${asset.version}`,
|
@@ -67,7 +68,7 @@ class AssetManager {
|
|
67
68
|
}
|
68
69
|
async getAsset(ref, noCache = false, autoFetch = true) {
|
69
70
|
ref = normalizeKapetaUri(ref);
|
70
|
-
const cacheKey =
|
71
|
+
const cacheKey = toKey(ref);
|
71
72
|
if (!noCache && cacheManager.has(cacheKey)) {
|
72
73
|
return cacheManager.get(cacheKey);
|
73
74
|
}
|
@@ -98,12 +99,19 @@ class AssetManager {
|
|
98
99
|
await repositoryManager.setSourceOfChangeFor(path, sourceOfChange);
|
99
100
|
await FS.writeFile(path, YAML.stringify(yaml));
|
100
101
|
const asset = await this.importFile(path);
|
101
|
-
|
102
|
+
asset.forEach((a) => {
|
103
|
+
const ref = normalizeKapetaUri(a.ref);
|
104
|
+
const key = toKey(ref);
|
105
|
+
cacheManager.set(key, a, CACHE_TTL);
|
106
|
+
});
|
107
|
+
definitionsManager.clearCache();
|
108
|
+
console.log(`Created asset at: ${path}`);
|
102
109
|
const ref = `kapeta://${yaml.metadata.name}:local`;
|
103
110
|
this.maybeGenerateCode(ref, path, yaml);
|
104
111
|
return asset;
|
105
112
|
}
|
106
113
|
async updateAsset(ref, yaml, sourceOfChange = 'filesystem') {
|
114
|
+
ref = normalizeKapetaUri(ref);
|
107
115
|
const asset = await this.getAsset(ref, true, false);
|
108
116
|
if (!asset) {
|
109
117
|
throw new Error('Attempted to update unknown asset: ' + ref);
|
@@ -116,8 +124,9 @@ class AssetManager {
|
|
116
124
|
}
|
117
125
|
await repositoryManager.setSourceOfChangeFor(asset.ymlPath, sourceOfChange);
|
118
126
|
await FS.writeFile(asset.ymlPath, YAML.stringify(yaml));
|
119
|
-
console.log(
|
120
|
-
cacheManager.
|
127
|
+
console.log(`Updated asset at: ${asset.ymlPath}`);
|
128
|
+
cacheManager.remove(toKey(ref));
|
129
|
+
definitionsManager.clearCache();
|
121
130
|
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
122
131
|
}
|
123
132
|
async importFile(filePath) {
|
@@ -131,8 +140,12 @@ class AssetManager {
|
|
131
140
|
const assetInfos = YAML.parseAllDocuments(content.toString()).map((doc) => doc.toJSON());
|
132
141
|
await Actions.link(new ProgressListener(), Path.dirname(filePath));
|
133
142
|
const version = 'local';
|
134
|
-
const refs = assetInfos.map((assetInfo) => `kapeta://${assetInfo.metadata.name}:${version}`);
|
135
|
-
|
143
|
+
const refs = assetInfos.map((assetInfo) => normalizeKapetaUri(`kapeta://${assetInfo.metadata.name}:${version}`));
|
144
|
+
refs.forEach((ref) => {
|
145
|
+
const key = toKey(ref);
|
146
|
+
cacheManager.remove(key);
|
147
|
+
});
|
148
|
+
definitionsManager.clearCache();
|
136
149
|
return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
|
137
150
|
}
|
138
151
|
async unregisterAsset(ref) {
|
@@ -140,7 +153,9 @@ class AssetManager {
|
|
140
153
|
if (!asset) {
|
141
154
|
throw new Error('Asset does not exists: ' + ref);
|
142
155
|
}
|
143
|
-
|
156
|
+
const key = toKey(ref);
|
157
|
+
cacheManager.remove(key);
|
158
|
+
definitionsManager.clearCache();
|
144
159
|
await Actions.uninstall(new ProgressListener(), [asset.ref]);
|
145
160
|
}
|
146
161
|
async installAsset(ref) {
|
@@ -150,6 +165,9 @@ class AssetManager {
|
|
150
165
|
}
|
151
166
|
const uri = parseKapetaUri(ref);
|
152
167
|
console.log('Installing %s', ref);
|
168
|
+
const key = toKey(ref);
|
169
|
+
cacheManager.remove(key);
|
170
|
+
definitionsManager.clearCache();
|
153
171
|
return await repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, false);
|
154
172
|
}
|
155
173
|
maybeGenerateCode(ref, ymlPath, block) {
|
@@ -2,7 +2,7 @@ export interface CacheEntry<T = any> {
|
|
2
2
|
expires: number;
|
3
3
|
data: T;
|
4
4
|
}
|
5
|
-
declare class CacheManager {
|
5
|
+
export declare class CacheManager {
|
6
6
|
private cache;
|
7
7
|
flush(): void;
|
8
8
|
doCached<T>(key: string, getter: () => T, ttl?: number): T;
|
@@ -10,7 +10,7 @@ declare class CacheManager {
|
|
10
10
|
set<T>(key: string, data: T, ttl?: number): void;
|
11
11
|
has(key: string): boolean;
|
12
12
|
remove(key: string): number;
|
13
|
+
removePrefix(key: string): void;
|
13
14
|
}
|
14
15
|
export declare const cacheManager: CacheManager;
|
15
16
|
export declare const doCached: <T>(key: string, getter: () => T, ttl?: number) => T;
|
16
|
-
export {};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import NodeCache from 'node-cache';
|
2
2
|
const DEFAULT_CACHE_TTL = 60 * 1000; // 1 min
|
3
|
-
class CacheManager {
|
3
|
+
export class CacheManager {
|
4
4
|
cache = new NodeCache();
|
5
5
|
flush() {
|
6
6
|
this.cache.flushAll();
|
@@ -26,6 +26,14 @@ class CacheManager {
|
|
26
26
|
remove(key) {
|
27
27
|
return this.cache.del(key);
|
28
28
|
}
|
29
|
+
removePrefix(key) {
|
30
|
+
const keys = this.cache.keys();
|
31
|
+
for (const k of keys) {
|
32
|
+
if (k.startsWith(key)) {
|
33
|
+
this.remove(k);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
29
37
|
}
|
30
38
|
export const cacheManager = new CacheManager();
|
31
39
|
export const doCached = (key, getter, ttl = DEFAULT_CACHE_TTL) => cacheManager.doCached(key, getter, ttl);
|
@@ -6,6 +6,7 @@ declare class DefinitionsManager {
|
|
6
6
|
exists(ref: string): boolean;
|
7
7
|
getProviderDefinitions(): DefinitionInfo[];
|
8
8
|
getDefinition(ref: string): DefinitionInfo | undefined;
|
9
|
+
clearCache(): void;
|
9
10
|
}
|
10
11
|
export declare const definitionsManager: DefinitionsManager;
|
11
12
|
export {};
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import ClusterConfiguration from '@kapeta/local-cluster-config';
|
2
2
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
3
|
-
import { doCached } from './cacheManager';
|
3
|
+
import { cacheManager, doCached } from './cacheManager';
|
4
4
|
class DefinitionsManager {
|
5
5
|
getHash(kindFilter) {
|
6
6
|
if (kindFilter) {
|
@@ -12,7 +12,7 @@ class DefinitionsManager {
|
|
12
12
|
return 'none';
|
13
13
|
}
|
14
14
|
getFullKey(kindFilter) {
|
15
|
-
return `
|
15
|
+
return `definitionsManager:${this.getHash(kindFilter)}`;
|
16
16
|
}
|
17
17
|
getDefinitions(kindFilter) {
|
18
18
|
const key = this.getFullKey(kindFilter);
|
@@ -33,5 +33,8 @@ class DefinitionsManager {
|
|
33
33
|
return parseKapetaUri(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
|
34
34
|
});
|
35
35
|
}
|
36
|
+
clearCache() {
|
37
|
+
cacheManager.removePrefix('definitionsManager:');
|
38
|
+
}
|
36
39
|
}
|
37
40
|
export const definitionsManager = new DefinitionsManager();
|
@@ -21,6 +21,12 @@ router.get('/', (req, res) => {
|
|
21
21
|
router.get('/:systemId/instances', (req, res) => {
|
22
22
|
res.send(instanceManager.getInstancesForPlan(req.params.systemId));
|
23
23
|
});
|
24
|
+
/**
|
25
|
+
* Get single instance in a plan
|
26
|
+
*/
|
27
|
+
router.get('/:systemId/instances/:instanceId', (req, res) => {
|
28
|
+
res.send(instanceManager.getInstance(req.params.systemId, req.params.instanceId));
|
29
|
+
});
|
24
30
|
/**
|
25
31
|
* Start all instances in a plan
|
26
32
|
*/
|
package/package.json
CHANGED
package/src/RepositoryWatcher.ts
CHANGED
@@ -6,8 +6,6 @@ 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 { definitionsManager } from './definitionsManager';
|
10
|
-
import { assetManager } from './assetManager';
|
11
9
|
import { SourceOfChange, WatchEventName } from './types';
|
12
10
|
import { cacheManager } from './cacheManager';
|
13
11
|
|
@@ -64,17 +62,25 @@ export class RepositoryWatcher {
|
|
64
62
|
|
65
63
|
async setSourceOfChangeFor(file: string, source: SourceOfChange) {
|
66
64
|
this.sourceOfChange.set(file, source);
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
try {
|
66
|
+
const realPath = await FS.realpath(file);
|
67
|
+
if (realPath !== file) {
|
68
|
+
this.sourceOfChange.set(realPath, source);
|
69
|
+
}
|
70
|
+
} catch (e) {
|
71
|
+
// Ignore
|
70
72
|
}
|
71
73
|
}
|
72
74
|
|
73
75
|
async clearSourceOfChangeFor(file: string) {
|
74
76
|
this.sourceOfChange.delete(file);
|
75
|
-
|
76
|
-
|
77
|
-
|
77
|
+
try {
|
78
|
+
const realPath = await FS.realpath(file);
|
79
|
+
if (realPath !== file) {
|
80
|
+
this.sourceOfChange.delete(realPath);
|
81
|
+
}
|
82
|
+
} catch (e) {
|
83
|
+
// Ignore
|
78
84
|
}
|
79
85
|
}
|
80
86
|
|
package/src/assetManager.ts
CHANGED
@@ -16,6 +16,8 @@ import { cacheManager } from './cacheManager';
|
|
16
16
|
|
17
17
|
const CACHE_TTL = 60 * 60 * 1000; // 1 hour
|
18
18
|
|
19
|
+
const toKey = (ref: string) => `assetManager:asset:${ref}`;
|
20
|
+
|
19
21
|
export interface EnrichedAsset {
|
20
22
|
ref: string;
|
21
23
|
editable: boolean;
|
@@ -99,7 +101,7 @@ class AssetManager {
|
|
99
101
|
autoFetch: boolean = true
|
100
102
|
): Promise<EnrichedAsset | undefined> {
|
101
103
|
ref = normalizeKapetaUri(ref);
|
102
|
-
const cacheKey =
|
104
|
+
const cacheKey = toKey(ref);
|
103
105
|
if (!noCache && cacheManager.has(cacheKey)) {
|
104
106
|
return cacheManager.get(cacheKey);
|
105
107
|
}
|
@@ -138,8 +140,14 @@ class AssetManager {
|
|
138
140
|
await repositoryManager.setSourceOfChangeFor(path, sourceOfChange);
|
139
141
|
await FS.writeFile(path, YAML.stringify(yaml));
|
140
142
|
const asset = await this.importFile(path);
|
143
|
+
asset.forEach((a) => {
|
144
|
+
const ref = normalizeKapetaUri(a.ref);
|
145
|
+
const key = toKey(ref);
|
146
|
+
cacheManager.set(key, a, CACHE_TTL);
|
147
|
+
});
|
141
148
|
|
142
|
-
|
149
|
+
definitionsManager.clearCache();
|
150
|
+
console.log(`Created asset at: ${path}`);
|
143
151
|
|
144
152
|
const ref = `kapeta://${yaml.metadata.name}:local`;
|
145
153
|
|
@@ -149,6 +157,7 @@ class AssetManager {
|
|
149
157
|
}
|
150
158
|
|
151
159
|
async updateAsset(ref: string, yaml: BlockDefinition, sourceOfChange: SourceOfChange = 'filesystem') {
|
160
|
+
ref = normalizeKapetaUri(ref);
|
152
161
|
const asset = await this.getAsset(ref, true, false);
|
153
162
|
if (!asset) {
|
154
163
|
throw new Error('Attempted to update unknown asset: ' + ref);
|
@@ -164,9 +173,10 @@ class AssetManager {
|
|
164
173
|
|
165
174
|
await repositoryManager.setSourceOfChangeFor(asset.ymlPath, sourceOfChange);
|
166
175
|
await FS.writeFile(asset.ymlPath, YAML.stringify(yaml));
|
167
|
-
console.log(
|
176
|
+
console.log(`Updated asset at: ${asset.ymlPath}`);
|
168
177
|
|
169
|
-
cacheManager.
|
178
|
+
cacheManager.remove(toKey(ref));
|
179
|
+
definitionsManager.clearCache();
|
170
180
|
|
171
181
|
this.maybeGenerateCode(asset.ref, asset.ymlPath, yaml);
|
172
182
|
}
|
@@ -186,9 +196,15 @@ class AssetManager {
|
|
186
196
|
await Actions.link(new ProgressListener(), Path.dirname(filePath));
|
187
197
|
|
188
198
|
const version = 'local';
|
189
|
-
const refs = assetInfos.map((assetInfo) =>
|
199
|
+
const refs = assetInfos.map((assetInfo) =>
|
200
|
+
normalizeKapetaUri(`kapeta://${assetInfo.metadata.name}:${version}`)
|
201
|
+
);
|
202
|
+
refs.forEach((ref) => {
|
203
|
+
const key = toKey(ref);
|
204
|
+
cacheManager.remove(key);
|
205
|
+
});
|
190
206
|
|
191
|
-
|
207
|
+
definitionsManager.clearCache();
|
192
208
|
|
193
209
|
return this.getAssets().filter((a) => refs.some((ref) => compareRefs(ref, a.ref)));
|
194
210
|
}
|
@@ -199,7 +215,9 @@ class AssetManager {
|
|
199
215
|
throw new Error('Asset does not exists: ' + ref);
|
200
216
|
}
|
201
217
|
|
202
|
-
|
218
|
+
const key = toKey(ref);
|
219
|
+
cacheManager.remove(key);
|
220
|
+
definitionsManager.clearCache();
|
203
221
|
|
204
222
|
await Actions.uninstall(new ProgressListener(), [asset.ref]);
|
205
223
|
}
|
@@ -211,6 +229,9 @@ class AssetManager {
|
|
211
229
|
}
|
212
230
|
const uri = parseKapetaUri(ref);
|
213
231
|
console.log('Installing %s', ref);
|
232
|
+
const key = toKey(ref);
|
233
|
+
cacheManager.remove(key);
|
234
|
+
definitionsManager.clearCache();
|
214
235
|
|
215
236
|
return await repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, false);
|
216
237
|
}
|
package/src/cacheManager.ts
CHANGED
@@ -5,7 +5,7 @@ export interface CacheEntry<T = any> {
|
|
5
5
|
expires: number;
|
6
6
|
data: T;
|
7
7
|
}
|
8
|
-
class CacheManager {
|
8
|
+
export class CacheManager {
|
9
9
|
private cache: NodeCache = new NodeCache();
|
10
10
|
|
11
11
|
public flush() {
|
@@ -37,6 +37,15 @@ class CacheManager {
|
|
37
37
|
public remove(key: string) {
|
38
38
|
return this.cache.del(key);
|
39
39
|
}
|
40
|
+
|
41
|
+
public removePrefix(key: string) {
|
42
|
+
const keys = this.cache.keys();
|
43
|
+
for (const k of keys) {
|
44
|
+
if (k.startsWith(key)) {
|
45
|
+
this.remove(k);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
40
49
|
}
|
41
50
|
|
42
51
|
export const cacheManager = new CacheManager();
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import ClusterConfiguration, { DefinitionInfo } from '@kapeta/local-cluster-config';
|
2
2
|
import { parseKapetaUri } from '@kapeta/nodejs-utils';
|
3
|
-
import { doCached } from './cacheManager';
|
3
|
+
import { cacheManager, doCached } from './cacheManager';
|
4
4
|
|
5
5
|
class DefinitionsManager {
|
6
6
|
private getHash(kindFilter?: string | string[]) {
|
@@ -14,7 +14,7 @@ class DefinitionsManager {
|
|
14
14
|
}
|
15
15
|
|
16
16
|
private getFullKey(kindFilter?: string | string[]) {
|
17
|
-
return `
|
17
|
+
return `definitionsManager:${this.getHash(kindFilter)}`;
|
18
18
|
}
|
19
19
|
|
20
20
|
public getDefinitions(kindFilter?: string | string[]): DefinitionInfo[] {
|
@@ -40,6 +40,10 @@ class DefinitionsManager {
|
|
40
40
|
return parseKapetaUri(`${d.definition.metadata.name}:${d.version}`).id === uri.id;
|
41
41
|
});
|
42
42
|
}
|
43
|
+
|
44
|
+
public clearCache() {
|
45
|
+
cacheManager.removePrefix('definitionsManager:');
|
46
|
+
}
|
43
47
|
}
|
44
48
|
|
45
49
|
export const definitionsManager = new DefinitionsManager();
|
package/src/instances/routes.ts
CHANGED
@@ -25,6 +25,13 @@ router.get('/:systemId/instances', (req: Request, res: Response) => {
|
|
25
25
|
res.send(instanceManager.getInstancesForPlan(req.params.systemId));
|
26
26
|
});
|
27
27
|
|
28
|
+
/**
|
29
|
+
* Get single instance in a plan
|
30
|
+
*/
|
31
|
+
router.get('/:systemId/instances/:instanceId', (req: Request, res: Response) => {
|
32
|
+
res.send(instanceManager.getInstance(req.params.systemId, req.params.instanceId));
|
33
|
+
});
|
34
|
+
|
28
35
|
/**
|
29
36
|
* Start all instances in a plan
|
30
37
|
*/
|