@social-mail/social-mail-web-server 1.4.778 → 1.4.779
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/dist/server/model/events/MailboxContactEvents.d.ts.map +1 -1
- package/dist/server/model/events/MailboxContactEvents.js +8 -17
- package/dist/server/model/events/MailboxContactEvents.js.map +1 -1
- package/dist/server/storage/LockFile.d.ts +2 -2
- package/dist/server/storage/LockFile.d.ts.map +1 -1
- package/dist/server/storage/LockFile.js +18 -15
- package/dist/server/storage/LockFile.js.map +1 -1
- package/dist/tests/core/lock-file/lock-file-test.d.ts +1 -1
- package/dist/tests/core/lock-file/lock-file-test.d.ts.map +1 -1
- package/dist/tests/core/lock-file/lock-file-test.js +15 -2
- package/dist/tests/core/lock-file/lock-file-test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/server/model/events/MailboxContactEvents.ts +8 -19
- package/src/server/storage/LockFile.ts +20 -15
- package/src/tests/core/lock-file/lock-file-test.ts +18 -2
package/package.json
CHANGED
|
@@ -47,8 +47,7 @@ export default class MailboxContactEvents extends AuthenticatedEvents<MailboxCon
|
|
|
47
47
|
|
|
48
48
|
async afterUpdate(entity: MailboxContact, entry: ChangeEntry<MailboxContact>) {
|
|
49
49
|
// if blocked was changed
|
|
50
|
-
const { mailboxID, blocked, autoClose } = entity;
|
|
51
|
-
let { openThreads , totalThreads } = entity;
|
|
50
|
+
const { mailboxID, blocked, autoClose, emailAddressID, openThreads } = entity;
|
|
52
51
|
|
|
53
52
|
const db = ServiceProvider.resolve(this, SocialMailContext);
|
|
54
53
|
if (entry.isUpdated("autoClose") || entry.isUpdated("blocked")) {
|
|
@@ -68,26 +67,16 @@ export default class MailboxContactEvents extends AuthenticatedEvents<MailboxCon
|
|
|
68
67
|
} else {
|
|
69
68
|
// we need to recalculate
|
|
70
69
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
&& x.threadID === x.emailID
|
|
70
|
+
const all = await db.emails
|
|
71
|
+
.where(entity , (p) => (x) => x.threadContacts.some((t) => t.mailboxID === p.mailboxID
|
|
72
|
+
&& t.emailAddressID === p.emailAddressID)
|
|
73
|
+
&& x.threadID === null
|
|
76
74
|
)
|
|
77
75
|
.sum(void 0, (p) => (x) => ({
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}));
|
|
81
|
-
|
|
82
|
-
if (t) {
|
|
83
|
-
openThreads = t.openThreads;
|
|
84
|
-
totalThreads = t.totalThreads;
|
|
85
|
-
}
|
|
86
|
-
await db.mailboxes.where({ mailboxID }, (p) => (x) => x.mailboxID === p.mailboxID)
|
|
87
|
-
.update({ openThreads, totalThreads }, (p) => (x) => ({
|
|
88
|
-
openThreads: Sql.math.max(0, x.openThreads + Sql.cast.asInteger(p.openThreads)),
|
|
89
|
-
totalThreads: Sql.math.max(0, x.totalThreads + Sql.cast.asInteger(p.totalThreads))
|
|
76
|
+
totalThreads: 1,
|
|
77
|
+
openThreads: x.lastReplyID === null ? 1 : 0
|
|
90
78
|
}));
|
|
79
|
+
await db.mailboxContacts.statements.update(all, { mailboxID, emailAddressID});
|
|
91
80
|
}
|
|
92
81
|
}
|
|
93
82
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { Stream } from "node:stream";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import { existsSync, mkdirSync, openSync, constants, writeSync, closeSync, unlinkSync, statSync } from "node:fs";
|
|
4
|
+
import { existsSync, mkdirSync, openSync, constants, writeSync, closeSync, unlinkSync, statSync, fdatasyncSync } from "node:fs";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
6
|
import * as os from "node:os";
|
|
7
7
|
import sleep from "../../common/sleep.js";
|
|
@@ -31,43 +31,48 @@ export default class LockFile implements Disposable {
|
|
|
31
31
|
|
|
32
32
|
const lockFile = join(lockFolder, hash + ".lock");
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
let now = Date.now();
|
|
35
|
+
const till = now + timeout;
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
do {
|
|
37
39
|
|
|
38
40
|
try {
|
|
39
41
|
// check if it exists..
|
|
40
42
|
if (!existsSync(lockFile)) {
|
|
41
43
|
// create and return..
|
|
42
|
-
|
|
43
|
-
writeSync(fd, "1");
|
|
44
|
-
return new LockFile(lockFile, fd);
|
|
44
|
+
return new LockFile(lockFile);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
const stat = statSync(lockFile);
|
|
48
|
-
const
|
|
49
|
-
if
|
|
50
|
-
//
|
|
48
|
+
const past = now - 15000;
|
|
49
|
+
if(stat.mtimeMs < past) {
|
|
50
|
+
// it is dead...
|
|
51
51
|
unlinkSync(lockFile);
|
|
52
|
-
continue;
|
|
53
52
|
}
|
|
54
|
-
|
|
55
53
|
} catch (error){
|
|
56
54
|
// do nothing
|
|
57
|
-
|
|
55
|
+
console.error(error);
|
|
58
56
|
}
|
|
59
57
|
await sleep(3000);
|
|
60
|
-
|
|
58
|
+
now = Date.now();
|
|
59
|
+
}while(now < till);
|
|
61
60
|
|
|
62
61
|
throw new Error("Could not acquire lock");
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
timer: any;
|
|
65
|
+
fd: any;
|
|
66
66
|
|
|
67
|
-
constructor(private readonly lockFile
|
|
67
|
+
constructor(private readonly lockFile) {
|
|
68
|
+
const fd = this.fd = openSync(lockFile, "wx", openMode);
|
|
69
|
+
let n = 1;
|
|
70
|
+
writeSync(fd, (n++) + "" );
|
|
71
|
+
fdatasyncSync(fd);
|
|
68
72
|
this.timer = setInterval(() => {
|
|
69
73
|
try {
|
|
70
|
-
writeSync(fd, "
|
|
74
|
+
writeSync(fd, (n++) + "" );
|
|
75
|
+
fdatasyncSync(fd);
|
|
71
76
|
} catch {
|
|
72
77
|
// do nothing
|
|
73
78
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import assert from "assert";
|
|
2
3
|
import sleep from "../../../common/sleep.js";
|
|
3
4
|
import LockFile from "../../../server/storage/LockFile.js";
|
|
5
|
+
import { closeSync } from "fs";
|
|
4
6
|
|
|
5
7
|
(Symbol as any).dispose ??= Symbol("dispose");
|
|
6
8
|
(Symbol as any).asyncDispose ??= Symbol("asyncDispose");
|
|
@@ -16,6 +18,13 @@ const lock1 = async () => {
|
|
|
16
18
|
console.log("Releasing lock 1");
|
|
17
19
|
};
|
|
18
20
|
|
|
21
|
+
const deadLock = async () => {
|
|
22
|
+
const l = await LockFile.lock("a1");
|
|
23
|
+
closeSync(l.fd);
|
|
24
|
+
l.fd = null;
|
|
25
|
+
clearInterval(l.timer);
|
|
26
|
+
};
|
|
27
|
+
|
|
19
28
|
const lock2 = async () => {
|
|
20
29
|
await sleep(10);
|
|
21
30
|
console.log("Opening lock 2");
|
|
@@ -26,9 +35,16 @@ const lock2 = async () => {
|
|
|
26
35
|
console.log("Releasing lock 2");
|
|
27
36
|
};
|
|
28
37
|
|
|
29
|
-
export default function() {
|
|
30
|
-
|
|
38
|
+
export default async function() {
|
|
39
|
+
await Promise.all([
|
|
31
40
|
lock1(),
|
|
32
41
|
lock2()
|
|
33
42
|
]);
|
|
43
|
+
|
|
44
|
+
console.log(`Trying Dead Lock`);
|
|
45
|
+
|
|
46
|
+
await Promise.all([
|
|
47
|
+
deadLock(),
|
|
48
|
+
lock2()
|
|
49
|
+
]);
|
|
34
50
|
}
|