@social-mail/social-mail-web-server 1.7.194 → 1.7.198

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.
Files changed (29) hide show
  1. package/dist/common/BaseDiskCache.d.ts +18 -0
  2. package/dist/common/BaseDiskCache.d.ts.map +1 -0
  3. package/dist/common/BaseDiskCache.js +190 -0
  4. package/dist/common/BaseDiskCache.js.map +1 -0
  5. package/dist/server/seed/ui/seed-ui.js +1 -1
  6. package/dist/server/services/cache/DiskCacheService.d.ts +3 -3
  7. package/dist/server/services/cache/DiskCacheService.d.ts.map +1 -1
  8. package/dist/server/services/cache/DiskCacheService.js +204 -176
  9. package/dist/server/services/cache/DiskCacheService.js.map +1 -1
  10. package/dist/server/services/captcha/CaptchaService.js +1 -1
  11. package/dist/server/services/captcha/CaptchaService.js.map +1 -1
  12. package/dist/server/storage/BaseStorage.d.ts.map +1 -1
  13. package/dist/server/storage/BaseStorage.js +3 -3
  14. package/dist/server/storage/BaseStorage.js.map +1 -1
  15. package/dist/server/storage/TempFileService.d.ts.map +1 -1
  16. package/dist/server/storage/TempFileService.js +8 -6
  17. package/dist/server/storage/TempFileService.js.map +1 -1
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/dist/wwwroot/routes/api/site/asset/index.d.ts.map +1 -1
  20. package/dist/wwwroot/routes/api/site/asset/index.js +5 -8
  21. package/dist/wwwroot/routes/api/site/asset/index.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/common/BaseDiskCache.ts +159 -0
  24. package/src/server/seed/ui/seed-ui.ts +1 -1
  25. package/src/server/services/cache/DiskCacheService.ts +230 -122
  26. package/src/server/services/captcha/CaptchaService.ts +1 -1
  27. package/src/server/storage/BaseStorage.ts +3 -2
  28. package/src/server/storage/TempFileService.ts +8 -6
  29. package/src/wwwroot/routes/api/site/asset/index.ts +7 -8
@@ -0,0 +1,18 @@
1
+ import { LocalFile } from "@entity-access/server-pages/dist/core/LocalFile.js";
2
+ export default class BaseDiskCache {
3
+ protected readonly root: string;
4
+ protected readonly keepTTLSeconds: number;
5
+ protected readonly minSize: number;
6
+ protected readonly updateAccessTime: boolean;
7
+ constructor({ root, keepTTLSeconds, minSize, updateAccessTime }: {
8
+ root: string;
9
+ keepTTLSeconds?: number;
10
+ minSize?: number;
11
+ updateAccessTime?: boolean;
12
+ });
13
+ get(path: string): Promise<LocalFile>;
14
+ getOrCreateAsync(path: string, factory: (fx: LocalFile) => Promise<void>, ext?: string): Promise<LocalFile>;
15
+ private clean;
16
+ private getFilesToDelete;
17
+ }
18
+ //# sourceMappingURL=BaseDiskCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseDiskCache.d.ts","sourceRoot":"","sources":["../../src/common/BaseDiskCache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,oDAAoD,CAAC;AAa/E,MAAM,CAAC,OAAO,OAAO,aAAa;IAE9B,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAChC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAC1C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACnC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;gBAEzC,EACI,IAAI,EACJ,cAAqB,EACrB,OAAiC,EACjC,gBAAuB,EAC1B,EAAE;QACC,IAAI,EAAE,MAAM,CAAC;QACb,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC9B;IAWC,GAAG,CAAC,IAAI,EAAE,MAAM;IAWhB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,SAAS;YAwC9E,KAAK;YAmCL,gBAAgB;CA8BjC"}
@@ -0,0 +1,190 @@
1
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
+ if (value !== null && value !== void 0) {
3
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
+ var dispose, inner;
5
+ if (async) {
6
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
+ dispose = value[Symbol.asyncDispose];
8
+ }
9
+ if (dispose === void 0) {
10
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
+ dispose = value[Symbol.dispose];
12
+ if (async) inner = dispose;
13
+ }
14
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
+ env.stack.push({ value: value, dispose: dispose, async: async });
17
+ }
18
+ else if (async) {
19
+ env.stack.push({ async: true });
20
+ }
21
+ return value;
22
+ };
23
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
+ return function (env) {
25
+ function fail(e) {
26
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
+ env.hasError = true;
28
+ }
29
+ function next() {
30
+ while (env.stack.length) {
31
+ var rec = env.stack.pop();
32
+ try {
33
+ var result = rec.dispose && rec.dispose.call(rec.value);
34
+ if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
35
+ }
36
+ catch (e) {
37
+ fail(e);
38
+ }
39
+ }
40
+ if (env.hasError) throw env.error;
41
+ }
42
+ return next();
43
+ };
44
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
45
+ var e = new Error(message);
46
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
47
+ });
48
+ /* eslint-disable no-console */
49
+ import { LocalFile } from "@entity-access/server-pages/dist/core/LocalFile.js";
50
+ import ensureDir from "./FileApi.js";
51
+ import LockFile from "../server/storage/LockFile.js";
52
+ import fsp, { stat, unlink } from "node:fs/promises";
53
+ import sleep from "./sleep.js";
54
+ import { existsSync } from "node:fs";
55
+ import { join, parse } from "node:path";
56
+ import { randomUUID } from "node:crypto";
57
+ import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
58
+ import { toKMBString } from "./NumberFormats.js";
59
+ const doNothing = () => void 0;
60
+ export default class BaseDiskCache {
61
+ constructor({ root, keepTTLSeconds = 3600, minSize = Number.MAX_SAFE_INTEGER, updateAccessTime = true }) {
62
+ this.root = root;
63
+ this.keepTTLSeconds = keepTTLSeconds;
64
+ this.minSize = minSize;
65
+ this.updateAccessTime = updateAccessTime;
66
+ ensureDir(root);
67
+ // eslint-disable-next-line no-console
68
+ setTimeout(() => this.clean().catch(console.error), 1000);
69
+ }
70
+ async get(path) {
71
+ path = join(this.root, path);
72
+ if (existsSync(path)) {
73
+ if (this.updateAccessTime) {
74
+ const now = new Date();
75
+ await fsp.utimes(path, now, now);
76
+ }
77
+ return new LocalFile(path, void 0, void 0, doNothing);
78
+ }
79
+ }
80
+ async getOrCreateAsync(path, factory, ext = ".dat") {
81
+ path = join(this.root, path);
82
+ const parsedPath = parse(path);
83
+ ensureDir(parsedPath.dir);
84
+ let error;
85
+ for (let index = 0; index < 10; index++) {
86
+ const env_1 = { stack: [], error: void 0, hasError: false };
87
+ try {
88
+ const lock = __addDisposableResource(env_1, await LockFile.lock(path), false);
89
+ if (existsSync(path)) {
90
+ if (this.updateAccessTime) {
91
+ const now = new Date();
92
+ await fsp.utimes(path, now, now);
93
+ }
94
+ return new LocalFile(path, void 0, void 0, doNothing);
95
+ }
96
+ const tmpPath = join(this.root, randomUUID() + (parsedPath.ext || ext));
97
+ await factory(new LocalFile(tmpPath, void 0, void 0, doNothing));
98
+ try {
99
+ await fsp.rename(tmpPath, path);
100
+ }
101
+ catch (e) {
102
+ if (existsSync(tmpPath)) {
103
+ unlink(tmpPath).catch(doNothing);
104
+ }
105
+ error = e;
106
+ await sleep(3000);
107
+ continue;
108
+ }
109
+ return new LocalFile(path, void 0, void 0, doNothing);
110
+ }
111
+ catch (e_1) {
112
+ env_1.error = e_1;
113
+ env_1.hasError = true;
114
+ }
115
+ finally {
116
+ __disposeResources(env_1);
117
+ }
118
+ }
119
+ throw new EntityAccessError(`Failed to write file due to error ${error.stack ?? error}`);
120
+ }
121
+ async clean() {
122
+ const env_2 = { stack: [], error: void 0, hasError: false };
123
+ try {
124
+ const l = __addDisposableResource(env_2, await LockFile.lock("clean-" + this.root, void 0, 10000), false);
125
+ let total = 0;
126
+ for (let i = 7; i > 0; i--) {
127
+ const s = await fsp.statfs(this.root);
128
+ const freeSize = s.bavail * s.bsize;
129
+ if (freeSize < this.minSize) {
130
+ try {
131
+ const keep = Date.now() - this.keepTTLSeconds * i;
132
+ const files = await this.getFilesToDelete(keep);
133
+ for (const file of files) {
134
+ // console.log(`Deleting ${file.path}`);
135
+ await unlink(file.path);
136
+ total += file.statInfo.size;
137
+ }
138
+ }
139
+ catch (error) {
140
+ console.error(error);
141
+ }
142
+ }
143
+ }
144
+ if (total) {
145
+ console.log(`${this.root} cleaned, ${toKMBString(total)} freed.`);
146
+ }
147
+ await sleep(30000);
148
+ setTimeout(() => this.clean().catch(console.error), 30000);
149
+ }
150
+ catch (e_2) {
151
+ env_2.error = e_2;
152
+ env_2.hasError = true;
153
+ }
154
+ finally {
155
+ __disposeResources(env_2);
156
+ }
157
+ }
158
+ async getFilesToDelete(oldest) {
159
+ const dir = await fsp.opendir(this.root, { recursive: true });
160
+ const filesToDelete = [];
161
+ try {
162
+ for await (const entry of dir) {
163
+ if (!entry.isFile()) {
164
+ continue;
165
+ }
166
+ const path = join(entry.parentPath, entry.name);
167
+ const statInfo = await stat(path);
168
+ if (statInfo.ctimeMs < oldest) {
169
+ filesToDelete.push({ path, statInfo });
170
+ if (filesToDelete.length === 1000) {
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ }
176
+ catch (error) {
177
+ console.error(error);
178
+ }
179
+ finally {
180
+ try {
181
+ await dir.close();
182
+ }
183
+ catch {
184
+ // do nothing
185
+ }
186
+ }
187
+ return filesToDelete;
188
+ }
189
+ }
190
+ //# sourceMappingURL=BaseDiskCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseDiskCache.js","sourceRoot":"","sources":["../../src/common/BaseDiskCache.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { UIPackageConfig } from "../../services/DBConfig.js";
2
2
  import semver from "semver";
3
3
  export default async function seedUI(config) {
4
- const version = "1.4.140";
4
+ const version = "1.4.152";
5
5
  const existing = await config.getValue(UIPackageConfig, false);
6
6
  if (existing) {
7
7
  if (semver.gte(existing.version, version)) {
@@ -1,7 +1,7 @@
1
1
  import { LocalFile } from "@entity-access/server-pages/dist/core/LocalFile.js";
2
- export default class DiskCacheService {
2
+ import BaseDiskCache from "../../../common/BaseDiskCache.js";
3
+ export default class DiskCacheService extends BaseDiskCache {
3
4
  constructor();
4
- getOrCreate(path: string, factory: (filePath: any) => Promise<void>, ext?: string): Promise<LocalFile>;
5
- clear(): Promise<void>;
5
+ link(localFile: LocalFile, fileName: string, contentType: string): Promise<LocalFile>;
6
6
  }
7
7
  //# sourceMappingURL=DiskCacheService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DiskCacheService.d.ts","sourceRoot":"","sources":["../../../../src/server/services/cache/DiskCacheService.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAE,MAAM,oDAAoD,CAAC;AAqB/E,MAAM,CAAC,OAAO,OAAO,gBAAgB;;IAQ3B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,QAAQ,KAAA,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,SAAS;IAyC5E,KAAK;CAiFd"}
1
+ {"version":3,"file":"DiskCacheService.d.ts","sourceRoot":"","sources":["../../../../src/server/services/cache/DiskCacheService.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,SAAS,EAAE,MAAM,oDAAoD,CAAC;AAG/E,OAAO,aAAa,MAAM,kCAAkC,CAAC;AAc7D,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,aAAa;;IA8FjD,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAQzE"}
@@ -7,197 +7,121 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
- var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
11
- if (value !== null && value !== void 0) {
12
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
13
- var dispose, inner;
14
- if (async) {
15
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
16
- dispose = value[Symbol.asyncDispose];
17
- }
18
- if (dispose === void 0) {
19
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
20
- dispose = value[Symbol.dispose];
21
- if (async) inner = dispose;
22
- }
23
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
24
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
25
- env.stack.push({ value: value, dispose: dispose, async: async });
26
- }
27
- else if (async) {
28
- env.stack.push({ async: true });
29
- }
30
- return value;
31
- };
32
- var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
33
- return function (env) {
34
- function fail(e) {
35
- env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
36
- env.hasError = true;
37
- }
38
- function next() {
39
- while (env.stack.length) {
40
- var rec = env.stack.pop();
41
- try {
42
- var result = rec.dispose && rec.dispose.call(rec.value);
43
- if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
44
- }
45
- catch (e) {
46
- fail(e);
47
- }
48
- }
49
- if (env.hasError) throw env.error;
50
- }
51
- return next();
52
- };
53
- })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
54
- var e = new Error(message);
55
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
56
- });
57
10
  /* eslint-disable no-console */
58
11
  import { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
59
- import { join, parse } from "path";
12
+ import { join } from "path";
60
13
  import { globalEnv } from "../../../common/globalEnv.js";
61
- import fsp from "node:fs/promises";
14
+ import { link } from "node:fs/promises";
62
15
  import FileSize from "../../../common/FileSize.js";
63
16
  import ensureDir from "../../../common/FileApi.js";
64
- import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
65
17
  import { LocalFile } from "@entity-access/server-pages/dist/core/LocalFile.js";
66
- import LockFile from "../../storage/LockFile.js";
67
- import { existsSync } from "fs";
18
+ import { unlinkSync } from "fs";
68
19
  import { randomUUID } from "crypto";
69
- import sleep from "../../../common/sleep.js";
70
- import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
71
- import { unlink } from "fs/promises";
20
+ import BaseDiskCache from "../../../common/BaseDiskCache.js";
72
21
  const cacheRoot = globalEnv.cacheDir;
73
22
  const serverCache = globalEnv.cacheDir;
74
23
  ensureDir(serverCache);
75
24
  const tempSize = FileSize.parse(globalEnv.tmpSize);
76
25
  const minSize = tempSize / 2;
77
26
  const doNothing = () => void 0;
78
- let DiskCacheService = class DiskCacheService {
27
+ let DiskCacheService = class DiskCacheService extends BaseDiskCache {
28
+ // } catch (e) {
29
+ // if (existsSync(tmpPath)) {
30
+ // unlink(tmpPath).catch(doNothing);
31
+ // }
32
+ // error = e;
33
+ // await sleep(3000);
34
+ // continue;
35
+ // }
36
+ // return new LocalFile(path, void 0, void 0, doNothing);
37
+ // }
38
+ // throw new EntityAccessError(`Failed to write file due to error ${error.stack ?? error}`);
39
+ // }
40
+ // async clear() {
41
+ // try {
42
+ // using l = await LockFile.lock("clean-" + cacheRoot, void 0, 10000);
43
+ // const s = await fsp.statfs(cacheRoot);
44
+ // const freeSize = s.bavail * s.bsize;
45
+ // if (freeSize < minSize) {
46
+ // let target = minSize - freeSize;
47
+ // const finalTarget = target;
48
+ // console.log(`Clearing temp files to delete ${target} bytes.`);
49
+ // let old = DateTime.now.addDays(-8);
50
+ // while(target > 0) {
51
+ // old = old.addDays(1);
52
+ // const dir = await fsp.opendir(cacheRoot, { recursive: true });
53
+ // const filesToDelete = [];
54
+ // try {
55
+ // for await (const entry of dir) {
56
+ // if (!entry.isFile()) {
57
+ // continue;
58
+ // }
59
+ // try {
60
+ // const filePath = join(entry.parentPath, entry.name);
61
+ // const st = await fsp.stat(filePath);
62
+ // if (st.mtimeMs < old.msSinceEpoch) {
63
+ // target -= st.size;
64
+ // if (filesToDelete.length < 100) {
65
+ // filesToDelete.push(filePath);
66
+ // } else {
67
+ // break;
68
+ // }
69
+ // // console.log(`${filePath} deleted.`);
70
+ // // await fsp.unlink(filePath);
71
+ // if (target < 0) {
72
+ // break;
73
+ // }
74
+ // }
75
+ // } catch {
76
+ // // we will ignore the error...
77
+ // }
78
+ // }
79
+ // } finally {
80
+ // try {
81
+ // await dir.close();
82
+ // } catch {
83
+ // // ignore error..
84
+ // }
85
+ // }
86
+ // for (const element of filesToDelete) {
87
+ // console.log(`${element} deleted.`);
88
+ // try {
89
+ // await fsp.unlink(element);
90
+ // } catch {
91
+ // // ignore this error as someone else might have deleted
92
+ // // it
93
+ // }
94
+ // }
95
+ // }
96
+ // console.log(`Temp folder cleared, ${finalTarget-target} bytes freed.`);
97
+ // }
98
+ // } catch (error) {
99
+ // console.error(error);
100
+ // }
101
+ // await sleep(30000);
102
+ // setTimeout(() => this.clear().catch(console.error), 60000);
103
+ // }
104
+ // async link(localFile: LocalFile, fileName: string, contentType: string) {
105
+ // const dir = join(serverCache, "tmp", randomUUID());
106
+ // ensureDir(dir);
107
+ // const path = join(dir, fileName);
108
+ // await link(localFile.path, path);
109
+ // return new LocalFile(path, fileName, contentType, () => unlinkSync(path));
110
+ // }
111
+ // }
79
112
  constructor() {
80
- // it is important to clean
81
- // in the beginning to avoid no file space errors.
82
- setTimeout(() => this.clear().catch(console.error), 1000);
83
- }
84
- async getOrCreate(path, factory, ext = ".dat") {
85
- path = join(serverCache, path);
86
- const parsedPath = parse(path);
87
- ensureDir(parsedPath.dir);
88
- let error;
89
- for (let index = 0; index < 10; index++) {
90
- const env_1 = { stack: [], error: void 0, hasError: false };
91
- try {
92
- const lock = __addDisposableResource(env_1, await LockFile.lock(path), false);
93
- if (existsSync(path)) {
94
- // change
95
- return new LocalFile(path, void 0, void 0, doNothing);
96
- }
97
- const tmpPath = join(serverCache, randomUUID() + (parsedPath.ext || ext));
98
- await factory(tmpPath);
99
- try {
100
- await fsp.rename(tmpPath, path);
101
- }
102
- catch (e) {
103
- if (existsSync(tmpPath)) {
104
- unlink(tmpPath).catch(doNothing);
105
- }
106
- error = e;
107
- await sleep(3000);
108
- continue;
109
- }
110
- return new LocalFile(path, void 0, void 0, doNothing);
111
- }
112
- catch (e_1) {
113
- env_1.error = e_1;
114
- env_1.hasError = true;
115
- }
116
- finally {
117
- __disposeResources(env_1);
118
- }
119
- }
120
- throw new EntityAccessError(`Failed to write file due to error ${error.stack ?? error}`);
113
+ super({
114
+ root: cacheRoot,
115
+ keepTTLSeconds: 86400,
116
+ minSize
117
+ });
121
118
  }
122
- async clear() {
123
- try {
124
- const env_2 = { stack: [], error: void 0, hasError: false };
125
- try {
126
- const l = __addDisposableResource(env_2, await LockFile.lock("clean-" + cacheRoot, void 0, 10000), false);
127
- const s = await fsp.statfs(cacheRoot);
128
- const freeSize = s.bavail * s.bsize;
129
- if (freeSize < minSize) {
130
- let target = minSize - freeSize;
131
- const finalTarget = target;
132
- console.log(`Clearing temp files to delete ${target} bytes.`);
133
- let old = DateTime.now.addDays(-8);
134
- while (target > 0) {
135
- old = old.addDays(1);
136
- const dir = await fsp.opendir(cacheRoot, { recursive: true });
137
- const filesToDelete = [];
138
- try {
139
- for await (const entry of dir) {
140
- if (!entry.isFile()) {
141
- continue;
142
- }
143
- try {
144
- const filePath = join(entry.path, entry.name);
145
- const st = await fsp.stat(filePath);
146
- if (st.mtimeMs < old.msSinceEpoch) {
147
- target -= st.size;
148
- if (filesToDelete.length < 100) {
149
- filesToDelete.push(filePath);
150
- }
151
- else {
152
- break;
153
- }
154
- // console.log(`${filePath} deleted.`);
155
- // await fsp.unlink(filePath);
156
- if (target < 0) {
157
- break;
158
- }
159
- }
160
- }
161
- catch {
162
- // we will ignore the error...
163
- }
164
- }
165
- }
166
- finally {
167
- try {
168
- await dir.close();
169
- }
170
- catch {
171
- // ignore error..
172
- }
173
- }
174
- for (const element of filesToDelete) {
175
- console.log(`${element} deleted.`);
176
- try {
177
- await fsp.unlink(element);
178
- }
179
- catch {
180
- // ignore this error as someone else might have deleted
181
- // it
182
- }
183
- }
184
- }
185
- console.log(`Temp folder cleared, ${finalTarget - target} bytes freed.`);
186
- }
187
- }
188
- catch (e_2) {
189
- env_2.error = e_2;
190
- env_2.hasError = true;
191
- }
192
- finally {
193
- __disposeResources(env_2);
194
- }
195
- }
196
- catch (error) {
197
- console.error(error);
198
- }
199
- await sleep(30000);
200
- setTimeout(() => this.clear().catch(console.error), 60000);
119
+ async link(localFile, fileName, contentType) {
120
+ const dir = join(this.root, "tmp", randomUUID());
121
+ ensureDir(dir);
122
+ const path = join(dir, fileName);
123
+ await link(localFile.path, path);
124
+ return new LocalFile(path, fileName, contentType, () => unlinkSync(path));
201
125
  }
202
126
  };
203
127
  DiskCacheService = __decorate([
@@ -205,4 +129,108 @@ DiskCacheService = __decorate([
205
129
  __metadata("design:paramtypes", [])
206
130
  ], DiskCacheService);
207
131
  export default DiskCacheService;
132
+ // constructor() {
133
+ // // it is important to clean
134
+ // // in the beginning to avoid no file space errors.
135
+ // setTimeout(() => this.clear().catch(console.error), 1000);
136
+ // }
137
+ // async getOrCreate(path: string, factory: (filePath) => Promise<void>, ext = ".dat" ) {
138
+ // path = join(serverCache, path);
139
+ // const parsedPath = parse(path);
140
+ // ensureDir(parsedPath.dir);
141
+ // let error: Error;
142
+ // for (let index = 0; index < 10; index++) {
143
+ // using lock = await LockFile.lock(path);
144
+ // if (existsSync(path)) {
145
+ // // change
146
+ // return new LocalFile(path, void 0, void 0, doNothing);
147
+ // }
148
+ // const tmpPath = join(serverCache, randomUUID() + (parsedPath.ext || ext));
149
+ // await factory(tmpPath);
150
+ // try {
151
+ // await fsp.rename(tmpPath, path);
152
+ // } catch (e) {
153
+ // if (existsSync(tmpPath)) {
154
+ // unlink(tmpPath).catch(doNothing);
155
+ // }
156
+ // error = e;
157
+ // await sleep(3000);
158
+ // continue;
159
+ // }
160
+ // return new LocalFile(path, void 0, void 0, doNothing);
161
+ // }
162
+ // throw new EntityAccessError(`Failed to write file due to error ${error.stack ?? error}`);
163
+ // }
164
+ // async clear() {
165
+ // try {
166
+ // using l = await LockFile.lock("clean-" + cacheRoot, void 0, 10000);
167
+ // const s = await fsp.statfs(cacheRoot);
168
+ // const freeSize = s.bavail * s.bsize;
169
+ // if (freeSize < minSize) {
170
+ // let target = minSize - freeSize;
171
+ // const finalTarget = target;
172
+ // console.log(`Clearing temp files to delete ${target} bytes.`);
173
+ // let old = DateTime.now.addDays(-8);
174
+ // while(target > 0) {
175
+ // old = old.addDays(1);
176
+ // const dir = await fsp.opendir(cacheRoot, { recursive: true });
177
+ // const filesToDelete = [];
178
+ // try {
179
+ // for await (const entry of dir) {
180
+ // if (!entry.isFile()) {
181
+ // continue;
182
+ // }
183
+ // try {
184
+ // const filePath = join(entry.parentPath, entry.name);
185
+ // const st = await fsp.stat(filePath);
186
+ // if (st.mtimeMs < old.msSinceEpoch) {
187
+ // target -= st.size;
188
+ // if (filesToDelete.length < 100) {
189
+ // filesToDelete.push(filePath);
190
+ // } else {
191
+ // break;
192
+ // }
193
+ // // console.log(`${filePath} deleted.`);
194
+ // // await fsp.unlink(filePath);
195
+ // if (target < 0) {
196
+ // break;
197
+ // }
198
+ // }
199
+ // } catch {
200
+ // // we will ignore the error...
201
+ // }
202
+ // }
203
+ // } finally {
204
+ // try {
205
+ // await dir.close();
206
+ // } catch {
207
+ // // ignore error..
208
+ // }
209
+ // }
210
+ // for (const element of filesToDelete) {
211
+ // console.log(`${element} deleted.`);
212
+ // try {
213
+ // await fsp.unlink(element);
214
+ // } catch {
215
+ // // ignore this error as someone else might have deleted
216
+ // // it
217
+ // }
218
+ // }
219
+ // }
220
+ // console.log(`Temp folder cleared, ${finalTarget-target} bytes freed.`);
221
+ // }
222
+ // } catch (error) {
223
+ // console.error(error);
224
+ // }
225
+ // await sleep(30000);
226
+ // setTimeout(() => this.clear().catch(console.error), 60000);
227
+ // }
228
+ // async link(localFile: LocalFile, fileName: string, contentType: string) {
229
+ // const dir = join(serverCache, "tmp", randomUUID());
230
+ // ensureDir(dir);
231
+ // const path = join(dir, fileName);
232
+ // await link(localFile.path, path);
233
+ // return new LocalFile(path, fileName, contentType, () => unlinkSync(path));
234
+ // }
235
+ // }
208
236
  //# sourceMappingURL=DiskCacheService.js.map