Skip to content

Commit aaa9f90

Browse files
committed
syncAcknowledge works now
1 parent 842c305 commit aaa9f90

File tree

6 files changed

+251
-21
lines changed

6 files changed

+251
-21
lines changed

packages/backend/src/delivery.ts

+59-10
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export default () => {
108108
next(e);
109109
}
110110
});
111-
111+
//TODO remove after storage refactoring
112112
router.post(
113113
'/messages/:ensName/syncAcknoledgment/:last_message_pull',
114114
async (req, res, next) => {
@@ -148,17 +148,66 @@ export default () => {
148148
contactEnsName,
149149
);
150150

151-
if (req.app.locals.db) {
152-
const db: IDatabase = req.app.locals.db;
151+
const db: IDatabase = req.app.locals.db;
152+
153+
await db.syncAcknowledge(
154+
conversationId,
155+
Number.parseInt(req.params.last_message_pull),
156+
);
157+
}),
158+
);
159+
160+
res.json();
161+
} catch (e) {
162+
next(e);
163+
}
164+
},
165+
);
166+
router.post(
167+
'/messages/:ensName/syncAcknowledgment/:last_message_pull',
168+
async (req, res, next) => {
169+
const hasValidParams = validateSchema(
170+
syncAcknoledgmentParamsSchema,
171+
req.params,
172+
);
173+
174+
const hasValidBody = validateSchema(
175+
syncAcknoledgmentBodySchema,
176+
req.body,
177+
);
178+
179+
// eslint-disable-next-line max-len
180+
//Express transform number inputs into strings. So we have to check if a string used as last_message_pull can be converted to a number later on.
181+
const isLastMessagePullNumber = !isNaN(
182+
Number.parseInt(req.params.last_message_pull),
183+
);
184+
185+
if (!hasValidParams || !isLastMessagePullNumber || !hasValidBody) {
186+
return res.send(400);
187+
}
188+
189+
try {
190+
const ensName = await req.app.locals.db.getIdEnsName(
191+
req.params.ensName,
192+
);
153193

154-
db.syncAcknoledgment(
155-
conversationId,
156-
ensName,
157-
req.params.last_message_pull,
194+
await Promise.all(
195+
req.body.acknoledgments.map(async (ack: Acknoledgment) => {
196+
const contactEnsName =
197+
await await req.app.locals.db.getIdEnsName(
198+
ack.contactAddress,
158199
);
159-
} else {
160-
throw Error('db not connected');
161-
}
200+
const conversationId = getConversationId(
201+
ensName,
202+
contactEnsName,
203+
);
204+
205+
const db: IDatabase = req.app.locals.db;
206+
207+
await db.syncAcknowledge(
208+
conversationId,
209+
Number.parseInt(req.params.last_message_pull),
210+
);
162211
}),
163212
);
164213

packages/backend/src/persistance/getDatabase.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import { UserStorage } from '@dm3-org/dm3-lib-storage';
99
import { createClient } from 'redis';
1010
import { getAliasChain, getIdEnsName } from './getIdEnsName';
1111
import Messages from './messages';
12-
import { syncAcknoledgment } from './messages/syncAcknoledgment';
1312
import Notification from './notification';
1413
import Pending from './pending';
1514
import Session from './session';
1615
import Storage from './storage';
16+
import { syncAcknowledge } from './messages/syncAcknowledge';
1717

1818
export enum RedisPrefix {
1919
Conversation = 'conversation:',
@@ -81,7 +81,7 @@ export async function getDatabase(_redis?: Redis): Promise<IDatabase> {
8181
deletePending: Pending.deletePending(redis),
8282
getIdEnsName: getIdEnsName(redis),
8383
getAliasChain: getAliasChain(redis),
84-
syncAcknoledgment: syncAcknoledgment(redis),
84+
syncAcknowledge: syncAcknowledge(redis),
8585
//Notification
8686
getUsersNotificationChannels:
8787
Notification.getUsersNotificationChannels(redis),
@@ -137,10 +137,9 @@ export interface IDatabase {
137137
deletePending: (ensName: string) => Promise<void>;
138138
getIdEnsName: (ensName: string) => Promise<string>;
139139
getAliasChain: (ensName: string) => Promise<string[]>;
140-
syncAcknoledgment: (
140+
syncAcknowledge: (
141141
conversationId: string,
142-
ensName: string,
143-
lastMessagePull: string,
142+
syncTime: number,
144143
) => Promise<void>;
145144
getUsersNotificationChannels: (
146145
ensName: string,
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { createMessage } from './createMessage';
22
import { deleteExpiredMessages } from './deleteExpiredMessages';
33
import { getMessages } from './getMessages';
4-
import { syncAcknoledgment } from './syncAcknoledgment';
4+
import { syncAcknowledge } from './syncAcknowledge';
55
import { getIncomingMessages } from './getIncomingMessages';
66
export default {
77
createMessage,
88
deleteExpiredMessages,
99
getMessages,
10-
syncAcknoledgment,
10+
syncAcknowledge,
1111
getIncomingMessages,
1212
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import { EncryptionEnvelop } from '@dm3-org/dm3-lib-messaging';
2+
import winston from 'winston';
3+
import { IDatabase, Redis, getDatabase, getRedisClient } from '../getDatabase';
4+
5+
const SENDER_ADDRESS = '0x25A643B6e52864d0eD816F1E43c0CF49C83B8292';
6+
const RECEIVER_ADDRESS = '0xDd36ae7F9a8E34FACf1e110c6e9d37D0dc917855';
7+
8+
global.logger = winston.createLogger({
9+
transports: [new winston.transports.Console()],
10+
});
11+
12+
describe('Sync Acknowledge', () => {
13+
let redisClient: Redis;
14+
let db: IDatabase;
15+
const logger = winston.createLogger({
16+
transports: [new winston.transports.Console()],
17+
});
18+
19+
beforeEach(async () => {
20+
redisClient = await getRedisClient();
21+
db = await getDatabase(redisClient);
22+
await redisClient.flushDb();
23+
});
24+
25+
afterEach(async () => {
26+
await redisClient.flushDb();
27+
await redisClient.disconnect();
28+
});
29+
30+
it('Removes acknowledged messages from DS', async () => {
31+
const envelop: EncryptionEnvelop = {
32+
message: '',
33+
metadata: {
34+
deliveryInformation: {
35+
to: RECEIVER_ADDRESS,
36+
from: SENDER_ADDRESS,
37+
},
38+
signature: '',
39+
encryptedMessageHash: '',
40+
version: '',
41+
encryptionScheme: 'x25519-chacha20-poly1305',
42+
},
43+
};
44+
45+
const conversionId = SENDER_ADDRESS + RECEIVER_ADDRESS;
46+
47+
const priorCreateMessages = await db.getIncomingMessages(
48+
RECEIVER_ADDRESS,
49+
10,
50+
);
51+
52+
expect(priorCreateMessages.length).toBe(0);
53+
54+
await db.createMessage(conversionId, envelop, 200);
55+
56+
const afterCreateMessages = await db.getIncomingMessages(
57+
RECEIVER_ADDRESS,
58+
10,
59+
);
60+
61+
expect(afterCreateMessages.length).toBe(1);
62+
63+
await db.syncAcknowledge(conversionId, 300);
64+
65+
const afterSyncAcknowledge = await db.getIncomingMessages(
66+
RECEIVER_ADDRESS,
67+
10,
68+
);
69+
70+
expect(afterSyncAcknowledge.length).toBe(0);
71+
});
72+
it('Keeps messages on the DS that have been created after the sync ', async () => {
73+
const envelop1: EncryptionEnvelop = {
74+
message: '',
75+
metadata: {
76+
deliveryInformation: {
77+
to: RECEIVER_ADDRESS,
78+
from: SENDER_ADDRESS,
79+
},
80+
signature: '',
81+
encryptedMessageHash: '',
82+
version: '',
83+
encryptionScheme: 'x25519-chacha20-poly1305',
84+
},
85+
};
86+
const envelop2: EncryptionEnvelop = {
87+
message: 'foo',
88+
metadata: {
89+
deliveryInformation: {
90+
to: RECEIVER_ADDRESS,
91+
from: SENDER_ADDRESS,
92+
},
93+
signature: '',
94+
encryptedMessageHash: '',
95+
version: '',
96+
encryptionScheme: 'x25519-chacha20-poly1305',
97+
},
98+
};
99+
const envelop3: EncryptionEnvelop = {
100+
message: 'bar',
101+
metadata: {
102+
deliveryInformation: {
103+
to: RECEIVER_ADDRESS,
104+
from: SENDER_ADDRESS,
105+
},
106+
signature: '',
107+
encryptedMessageHash: '',
108+
version: '',
109+
encryptionScheme: 'x25519-chacha20-poly1305',
110+
},
111+
};
112+
113+
const conversionId = SENDER_ADDRESS + RECEIVER_ADDRESS;
114+
115+
const priorCreateMessages = await db.getIncomingMessages(
116+
RECEIVER_ADDRESS,
117+
10,
118+
);
119+
120+
expect(priorCreateMessages.length).toBe(0);
121+
122+
await db.createMessage(conversionId, envelop1, 200);
123+
await db.createMessage(conversionId, envelop2, 301);
124+
await db.createMessage(conversionId, envelop3, 302);
125+
126+
const afterCreateMessages = await db.getIncomingMessages(
127+
RECEIVER_ADDRESS,
128+
10,
129+
);
130+
131+
expect(afterCreateMessages.length).toBe(3);
132+
133+
await db.syncAcknowledge(conversionId, 300);
134+
135+
let afterSyncAcknowledge = await db.getIncomingMessages(
136+
RECEIVER_ADDRESS,
137+
10,
138+
);
139+
140+
expect(afterSyncAcknowledge.length).toBe(2);
141+
142+
await db.syncAcknowledge(conversionId, 303);
143+
144+
afterSyncAcknowledge = await db.getIncomingMessages(
145+
RECEIVER_ADDRESS,
146+
10,
147+
);
148+
expect(afterSyncAcknowledge.length).toBe(0);
149+
});
150+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Redis, RedisPrefix } from '../getDatabase';
2+
export function syncAcknowledge(redis: Redis) {
3+
return async (conversationId: string, syncTime: number) => {
4+
await redis.zRemRangeByScore(
5+
RedisPrefix.Conversation + conversationId,
6+
0,
7+
syncTime,
8+
);
9+
};
10+
}

packages/lib/delivery-api/src/messaging-http.ts

+26-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,28 @@ import { checkAccount, getAxiosConfig } from './utils';
1111

1212
const DELIVERY_PATH = process.env.REACT_APP_BACKEND + '/delivery';
1313

14+
//TOOD REMOVE AFTER STORAGE REFACTOR
15+
export async function syncAcknoledgment(
16+
provider: ethers.providers.JsonRpcProvider,
17+
account: Account,
18+
acknoledgments: Acknoledgment[],
19+
token: string,
20+
lastMessagePull: number,
21+
): Promise<void> {
22+
const { profile } = checkAccount(account);
23+
24+
const url = `${DELIVERY_PATH}/messages/${normalizeEnsName(
25+
account!.ensName,
26+
)}/syncAcknoledgment/${lastMessagePull}`;
27+
28+
return getDeliveryServiceClient(
29+
profile,
30+
provider,
31+
async (url: string) => (await axios.get(url)).data,
32+
).post(url, { acknoledgments }, getAxiosConfig(token));
33+
}
34+
export type SyncAcknoledgment = typeof syncAcknoledgment;
35+
1436
/**
1537
* let the delivery service know that messages have been stored
1638
* and can be deleted on the delivery service
@@ -20,26 +42,26 @@ const DELIVERY_PATH = process.env.REACT_APP_BACKEND + '/delivery';
2042
* @param token The auth token
2143
* @param lastMessagePull Timestamp of the last message pull
2244
*/
23-
export async function syncAcknoledgment(
45+
export async function syncAcknowledgment(
2446
provider: ethers.providers.JsonRpcProvider,
2547
account: Account,
2648
acknoledgments: Acknoledgment[],
2749
token: string,
28-
lastMessagePull: number,
50+
lastSyncTime: number,
2951
): Promise<void> {
3052
const { profile } = checkAccount(account);
3153

3254
const url = `${DELIVERY_PATH}/messages/${normalizeEnsName(
3355
account!.ensName,
34-
)}/syncAcknoledgment/${lastMessagePull}`;
56+
)}/syncAcknowledgment/${lastSyncTime}`;
3557

3658
return getDeliveryServiceClient(
3759
profile,
3860
provider,
3961
async (url: string) => (await axios.get(url)).data,
4062
).post(url, { acknoledgments }, getAxiosConfig(token));
4163
}
42-
export type SyncAcknoledgment = typeof syncAcknoledgment;
64+
export type SyncAcknowledgment = typeof syncAcknoledgment;
4365

4466
/**
4567
* returns the bufferd message which were send form contactEnsName

0 commit comments

Comments
 (0)