@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-web-server",
3
- "version": "1.4.778",
3
+ "version": "1.4.779",
4
4
  "description": "## Phase 1",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -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 t = await db.emails.where(entity, (p) => (x) =>
72
- x.threadContacts
73
- .some((tc) => tc.mailboxID === p.mailboxID
74
- && tc.emailAddressID === p.emailAddressID)
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
- openThreads: x.closed === null ? 1 : 0,
79
- totalThreads: 1
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
- const till = Date.now() + timeout;
34
+ let now = Date.now();
35
+ const till = now + timeout;
35
36
 
36
- while(Date.now() < till) {
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
- const fd = openSync(lockFile, "wx", openMode);
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 diff = Date.now() - stat.mtimeMs;
49
- if (diff > 30000) {
50
- // most likely this is dead...
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
- // console.error(error);
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, private readonly fd) {
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, "1");
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
- return Promise.all([
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
  }