@social-mail/social-mail-web-server 1.7.232 → 1.7.233
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/WebServer.d.ts.map +1 -1
- package/dist/WebServer.js +0 -2
- package/dist/WebServer.js.map +1 -1
- package/dist/common/GlobalEvents.d.ts +1 -47
- package/dist/common/GlobalEvents.d.ts.map +1 -1
- package/dist/common/GlobalEvents.js +231 -243
- package/dist/common/GlobalEvents.js.map +1 -1
- package/dist/common/globalEnv.d.ts +9 -0
- package/dist/common/globalEnv.d.ts.map +1 -1
- package/dist/common/globalEnv.js +9 -0
- package/dist/common/globalEnv.js.map +1 -1
- package/dist/server/model/events/DomainKeyEvents.d.ts +0 -1
- package/dist/server/model/events/DomainKeyEvents.d.ts.map +1 -1
- package/dist/server/model/events/DomainKeyEvents.js +0 -5
- package/dist/server/model/events/DomainKeyEvents.js.map +1 -1
- package/dist/server/model/events/WebSiteHostEvents.d.ts +0 -1
- package/dist/server/model/events/WebSiteHostEvents.d.ts.map +1 -1
- package/dist/server/model/events/WebSiteHostEvents.js +1 -15
- package/dist/server/model/events/WebSiteHostEvents.js.map +1 -1
- package/dist/server/services/message-events/MessagingService.d.ts +17 -0
- package/dist/server/services/message-events/MessagingService.d.ts.map +1 -0
- package/dist/server/services/message-events/MessagingService.js +42 -0
- package/dist/server/services/message-events/MessagingService.js.map +1 -0
- package/dist/server/services/message-events/PgEvents.d.ts +13 -0
- package/dist/server/services/message-events/PgEvents.d.ts.map +1 -0
- package/dist/server/services/message-events/PgEvents.js +215 -0
- package/dist/server/services/message-events/PgEvents.js.map +1 -0
- package/dist/server/smtp/services/WebSiteChannelService.d.ts +0 -2
- package/dist/server/smtp/services/WebSiteChannelService.d.ts.map +1 -1
- package/dist/server/smtp/services/WebSiteChannelService.js +6 -20
- package/dist/server/smtp/services/WebSiteChannelService.js.map +1 -1
- package/dist/server/workflows/dns/SyncDnsZoneRecordsWorkflow.d.ts +2 -2
- package/dist/server/workflows/dns/SyncDnsZoneRecordsWorkflow.d.ts.map +1 -1
- package/dist/server/workflows/dns/SyncDnsZoneRecordsWorkflow.js +4 -4
- package/dist/server/workflows/dns/SyncDnsZoneRecordsWorkflow.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/WebServer.ts +0 -3
- package/src/common/GlobalEvents.ts +249 -249
- package/src/common/globalEnv.ts +11 -0
- package/src/server/model/events/DomainKeyEvents.ts +0 -5
- package/src/server/model/events/WebSiteHostEvents.ts +0 -4
- package/src/server/services/message-events/MessagingService.ts +43 -0
- package/src/server/services/message-events/PgEvents.ts +153 -0
- package/src/server/smtp/services/WebSiteChannelService.ts +5 -22
- package/src/server/workflows/dns/SyncDnsZoneRecordsWorkflow.ts +3 -3
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import Inject, { RegisterSingleton } from "@entity-access/entity-access/dist/di/di.js";
|
|
3
|
+
import pg from "pg";
|
|
4
|
+
import sleep from "../../../common/sleep.js";
|
|
5
|
+
import { globalEnv } from "../../../common/globalEnv.js";
|
|
6
|
+
import LockFile from "../../storage/LockFile.js";
|
|
7
|
+
|
|
8
|
+
export type messageTypes = string;
|
|
9
|
+
|
|
10
|
+
@RegisterSingleton
|
|
11
|
+
export default class PgEvents {
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
private _client: Promise<pg.Client>;
|
|
15
|
+
private _running: Promise<any>;
|
|
16
|
+
|
|
17
|
+
private handlers: Map<string,{ original: messageTypes, listening: boolean, handler: (message: messageTypes, payload) => any}[]> = new Map();
|
|
18
|
+
private added: string[] = [];
|
|
19
|
+
private removed: string[] = [];
|
|
20
|
+
|
|
21
|
+
private get client() {
|
|
22
|
+
return this._client ??= (async () => {
|
|
23
|
+
try {
|
|
24
|
+
const c = new pg.Client(globalEnv.pgEvents);
|
|
25
|
+
await c.connect();
|
|
26
|
+
c.on("error", () => {
|
|
27
|
+
try {
|
|
28
|
+
c.end().catch(console.error);
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error(error);
|
|
31
|
+
}
|
|
32
|
+
this._client = null;
|
|
33
|
+
});
|
|
34
|
+
c.on("end", () => this._client = null);
|
|
35
|
+
c.on("notification", async ({ channel, payload}) => {
|
|
36
|
+
try {
|
|
37
|
+
console.log(`Notification received ${channel}`);
|
|
38
|
+
const fx = this.handlers.get(channel);
|
|
39
|
+
if (fx) {
|
|
40
|
+
for (const { original, handler } of fx) {
|
|
41
|
+
try {
|
|
42
|
+
const p = handler(original as any, JSON.parse(payload));
|
|
43
|
+
if (p?.then) {
|
|
44
|
+
p.catch(console.error);
|
|
45
|
+
}
|
|
46
|
+
} catch (e) {
|
|
47
|
+
console.error(e);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(error);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
return c;
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(error);
|
|
58
|
+
}
|
|
59
|
+
})();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async emit(message: messageTypes, payload) {
|
|
63
|
+
/**
|
|
64
|
+
* Improve sending messages by queueing
|
|
65
|
+
*/
|
|
66
|
+
try {
|
|
67
|
+
let lastError = null;
|
|
68
|
+
for(let i=0;i<10;i++) {
|
|
69
|
+
|
|
70
|
+
// locking queue messages
|
|
71
|
+
using fx = await LockFile.lock(`pg-events-msg${message}`);
|
|
72
|
+
|
|
73
|
+
const id = "social_" + message.replace(/[^a-zA-Z0-9]/g, "_");
|
|
74
|
+
const c = new pg.Client(globalEnv.pgEvents);
|
|
75
|
+
try {
|
|
76
|
+
await c.connect();
|
|
77
|
+
await c.query("select pg_notify($1,$2)", [ id, JSON.stringify(payload || null)]);
|
|
78
|
+
break;
|
|
79
|
+
} catch (e) {
|
|
80
|
+
lastError = e;
|
|
81
|
+
continue;
|
|
82
|
+
} finally {
|
|
83
|
+
await c.end();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (lastError) {
|
|
87
|
+
console.error(lastError);
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error(error);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async listen(message: messageTypes, fx: (msg: messageTypes, payload: any) => any): Promise<AsyncDisposable> {
|
|
95
|
+
|
|
96
|
+
const id = "social_" + message.replace(/[^a-zA-Z0-9]/g, "_");
|
|
97
|
+
let handlers = this.handlers.get(id);
|
|
98
|
+
if(!handlers) {
|
|
99
|
+
handlers = [];
|
|
100
|
+
this.handlers.set(id, handlers);
|
|
101
|
+
}
|
|
102
|
+
handlers.push({ original: message, listening: false, handler: fx });
|
|
103
|
+
// client.query(`LISTEN ${id}`).catch(console.error);
|
|
104
|
+
console.log(`Listening for ${message} as ${id} on pg`);
|
|
105
|
+
this.added.push(id);
|
|
106
|
+
this.update().catch(console.error);
|
|
107
|
+
return {
|
|
108
|
+
[Symbol.asyncDispose]: async () => {
|
|
109
|
+
try {
|
|
110
|
+
this.handlers.delete(id);
|
|
111
|
+
this.removed.push(id);
|
|
112
|
+
this.update().catch(console.error);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.warn(error);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private update() {
|
|
121
|
+
return this._running ??= (async () => {
|
|
122
|
+
while(this.handlers.size) {
|
|
123
|
+
try {
|
|
124
|
+
const c = await this.client;
|
|
125
|
+
if (!c) {
|
|
126
|
+
await sleep(3000);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (this.added.length) {
|
|
130
|
+
const added = [... this.added];
|
|
131
|
+
this.added.length = 0;
|
|
132
|
+
for (const iterator of added) {
|
|
133
|
+
await c.query(`LISTEN ${iterator};`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (this.removed.length) {
|
|
137
|
+
const removed = [... this.removed];
|
|
138
|
+
this.removed.length = 0;
|
|
139
|
+
for (const iterator of removed) {
|
|
140
|
+
await c.query(`UNLISTEN ${iterator};`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
await c.query("select 1;");
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error(error);
|
|
146
|
+
}
|
|
147
|
+
await sleep(30000);
|
|
148
|
+
}
|
|
149
|
+
this._running = null;
|
|
150
|
+
})();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}
|
|
@@ -1,32 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
import Inject, { RegisterScoped, RegisterSingleton, RegisterTransient, ServiceCollection, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
3
3
|
import SocialMailContext from "../../model/SocialMailContext.js";
|
|
4
|
-
import GlobalEvents from "../../../common/GlobalEvents.js";
|
|
5
4
|
import { cacheFor, ICacheContainer, ObjectCache } from "../../../common/cacheFor.js";
|
|
5
|
+
import MessagingService from "../../services/message-events/MessagingService.js";
|
|
6
6
|
|
|
7
7
|
export default class WebSiteChannelService implements ICacheContainer<WebSiteChannelService> {
|
|
8
8
|
|
|
9
9
|
cache: ObjectCache<WebSiteChannelService>;
|
|
10
10
|
|
|
11
|
-
@Inject
|
|
12
|
-
globalEvents: GlobalEvents;
|
|
13
|
-
|
|
14
|
-
// @cacheFor()
|
|
15
|
-
// async getMailboxes(host: string) {
|
|
16
|
-
// using scope = ServiceProvider.createScope(this);
|
|
17
|
-
// const db = scope.resolve(SocialMailContext);
|
|
18
|
-
|
|
19
|
-
// host = host?.toLocaleLowerCase() ?? "localhost";
|
|
20
|
-
|
|
21
|
-
// const mailboxes = await db.mailboxes.where({ host}, (p) => (x) =>
|
|
22
|
-
// x.websiteChannels
|
|
23
|
-
// .some((w) => w.website.hosts
|
|
24
|
-
// .some((h)=> h.host === p.host)))
|
|
25
|
-
// .toArray();
|
|
26
|
-
|
|
27
|
-
// return mailboxes.map((x) => x.mailboxID);
|
|
28
|
-
// }
|
|
29
|
-
|
|
30
11
|
@cacheFor()
|
|
31
12
|
async getChannelAssociations(host: string) {
|
|
32
13
|
using scope = ServiceProvider.createScope(this);
|
|
@@ -57,11 +38,13 @@ export default class WebSiteChannelService implements ICacheContainer<WebSiteCha
|
|
|
57
38
|
}
|
|
58
39
|
|
|
59
40
|
clear() {
|
|
60
|
-
|
|
41
|
+
const ms = ServiceProvider.resolve(this, MessagingService).channelRefresh;
|
|
42
|
+
ms.notify("clear");
|
|
61
43
|
}
|
|
62
44
|
|
|
63
45
|
protected postInit() {
|
|
64
|
-
|
|
46
|
+
const ms = ServiceProvider.resolve(this, MessagingService).channelRefresh;
|
|
47
|
+
ms.on(() => this.cache?.clear("getChannelAssociations") );
|
|
65
48
|
}
|
|
66
49
|
|
|
67
50
|
}
|
|
@@ -6,8 +6,8 @@ import SocialMailContext from "../../model/SocialMailContext.js";
|
|
|
6
6
|
import EmailAddressService from "../../services/EmailAddressService.js";
|
|
7
7
|
import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
|
|
8
8
|
import { globalEnv } from "../../../common/globalEnv.js";
|
|
9
|
-
import GlobalEvents from "../../../common/GlobalEvents.js";
|
|
10
9
|
import StringFormat from "../../../common/StringFormat.js";
|
|
10
|
+
import MessagingService from "../../services/message-events/MessagingService.js";
|
|
11
11
|
|
|
12
12
|
const toUnixDateAndHour = (date: Date | DateTime, d = DateTime.from(date)) =>
|
|
13
13
|
`${StringFormat.fixed(d.year, 4)}${StringFormat.fixed(d.month)}${StringFormat.fixed(d.day)}${StringFormat.fixed(d.hour)}`;
|
|
@@ -35,11 +35,11 @@ export default class SyncDnsZoneRecordsWorkflow extends Workflow {
|
|
|
35
35
|
@UniqueActivity
|
|
36
36
|
async notifyDns(
|
|
37
37
|
@Inject db?: SocialMailContext,
|
|
38
|
-
@Inject
|
|
38
|
+
@Inject ms?: MessagingService
|
|
39
39
|
) {
|
|
40
40
|
const zoneID = this.input;
|
|
41
41
|
await db.hostedZones.statements.update({ dateSigned: null, dateUpdated: DateTime.now }, { zoneID });
|
|
42
|
-
|
|
42
|
+
ms.refreshDns.notify({ serverID: globalEnv.serverID });
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
@UniqueActivity
|