Skip to content

Commit 514cc62

Browse files
authored
Merge pull request #188 from CirclesUBI/feature/app-336-parallel-invitation-redemption-fails
Feature/app 336 parallel invitation redemption fails
2 parents 31da3b0 + c5ad3fc commit 514cc62

File tree

6 files changed

+74
-24
lines changed

6 files changed

+74
-24
lines changed

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@o-platform/api-server",
3-
"version": "0.9.5",
3+
"version": "0.9.6",
44
"description": "",
55
"main": "dist/index.js",
66
"prepublish": "tsc",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- migrate:up
2+
create table "ApiServers" (
3+
id serial primary key,
4+
"createdAt" timestamp with time zone not null default now(),
5+
"instanceId" text not null unique
6+
);
7+
8+
-- migrate:down

src/api-db/schema_template.prisma

+6
Original file line numberDiff line numberDiff line change
@@ -433,3 +433,9 @@ model Businesses {
433433
description String
434434
picture String
435435
}
436+
437+
model ApiServers {
438+
id Int @id @default(autoincrement())
439+
createdAt DateTime @default(now())
440+
instanceId String // A random value created at startup of an api-server instance
441+
}

src/environment.ts

+51-21
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ export enum UploadTarget {
2323
}
2424

2525
export class Environment {
26+
private static _instanceSpecificInvitationSafe: GnosisSafeProxy;
27+
private static _instanceSpecificInvitationSafeKey: string;
28+
2629
static async validateAndSummarize(logInfo: boolean = true) {
2730
const errors: string[] = [];
2831

@@ -81,20 +84,6 @@ export class Environment {
8184
if (logInfo) {
8285
console.log(` ${this.operatorOrganisationAddress} nonce is: ${nonce}`);
8386
}
84-
if (!process.env.INVITATION_FUNDS_SAFE_ADDRESS) {
85-
errors.push(`The INVITATION_FUNDS_SAFE_ADDRESS environment variable is not set.`);
86-
}
87-
88-
if (logInfo) {
89-
console.log("* Testing invitationFundsSafe ..");
90-
}
91-
nonce = await this.invitationFundsSafe.getNonce();
92-
if (logInfo) {
93-
console.log(` ${this.invitationFundsSafe.address} nonce is: ${nonce}`);
94-
}
95-
if (!process.env.INVITATION_FUNDS_SAFE_KEY) {
96-
errors.push(`The INVITATION_FUNDS_SAFE_KEY environment variable is not set.`);
97-
}
9887

9988
if (logInfo) {
10089
console.log(`* Checking which upload target to use (S3 or GCS) ...`);
@@ -147,18 +136,62 @@ export class Environment {
147136
console.log(` Success`);
148137
console.log(`* Testing connection to the readonly api-db ...`);
149138
}
139+
150140
await this.readonlyApiDb.$queryRaw`select 1`;
151141

152142
if (logInfo) {
153143
console.log(` Success`);
154144
console.log(`* Testing connection to the read/write api-db ...`);
155145
}
156146

157-
await this.readWriteApiDb.$queryRaw`select 1`;
147+
const apiServerRecord = await this.readWriteApiDb.$queryRaw`insert into "ApiServers" ("instanceId") values (${this.instanceId}) returning id;`;
148+
const apiServerRecordId = <number>(<any>apiServerRecord)[0]?.id;
158149

159150
if (logInfo) {
160-
console.log(` Success`);
151+
console.log(` Success. ApiServer record id: ${apiServerRecordId}`);
152+
}
161153

154+
if (!process.env.INVITATION_FUNDS_SAFE_ADDRESS) {
155+
errors.push(`The INVITATION_FUNDS_SAFE_ADDRESS environment variable is not set.`);
156+
}
157+
158+
const invitationFundsSafeAddresses = process.env.INVITATION_FUNDS_SAFE_ADDRESS?.split(";") ?? [];
159+
invitationFundsSafeAddresses.forEach((address) => {
160+
if (RpcGateway.get().utils.isAddress(address)) {
161+
return;
162+
}
163+
errors.push(`The INVITATION_FUNDS_SAFE_ADDRESS environment variable contains an invalid address: ${address}`);
164+
});
165+
RpcGateway.get().utils.isAddress(invitationFundsSafeAddresses[0]);
166+
167+
168+
if (!process.env.INVITATION_FUNDS_SAFE_KEY) {
169+
errors.push(`The INVITATION_FUNDS_SAFE_KEY environment variable is not set.`);
170+
}
171+
172+
const invitationFundsSafeKeys = process.env.INVITATION_FUNDS_SAFE_KEY?.split(";") ?? [];
173+
if (invitationFundsSafeKeys.length != invitationFundsSafeAddresses.length) {
174+
errors.push(
175+
`The INVITATION_FUNDS_SAFE_KEY environment variable contains a different number of keys than INVITATION_FUNDS_SAFE_ADDRESS contains addresses.`
176+
);
177+
}
178+
179+
const keyIdx = apiServerRecordId % invitationFundsSafeAddresses.length;
180+
this._instanceSpecificInvitationSafe = new GnosisSafeProxy(
181+
RpcGateway.get(),
182+
RpcGateway.get().utils.toChecksumAddress(<string>invitationFundsSafeAddresses[keyIdx])
183+
);
184+
this._instanceSpecificInvitationSafeKey = invitationFundsSafeKeys[keyIdx];
185+
186+
if (logInfo) {
187+
console.log("* Testing invitationFundsSafe ..");
188+
}
189+
nonce = await this.invitationFundsSafe.getNonce();
190+
if (logInfo) {
191+
console.log(` ${this.invitationFundsSafe.address} nonce is: ${nonce}`);
192+
}
193+
194+
if (logInfo) {
162195
console.log(`* Testing connection to the indexer ws endpoint (${this.blockchainIndexerUrl}) ...`);
163196
}
164197

@@ -382,15 +415,12 @@ export class Environment {
382415
}
383416

384417
static get invitationFundsSafe(): GnosisSafeProxy {
385-
return new GnosisSafeProxy(
386-
RpcGateway.get(),
387-
RpcGateway.get().utils.toChecksumAddress(<string>process.env.INVITATION_FUNDS_SAFE_ADDRESS)
388-
);
418+
return this._instanceSpecificInvitationSafe;
389419
}
390420

391421
static get invitationFundsSafeOwner(): Account {
392422
return RpcGateway.get().eth.accounts.privateKeyToAccount(
393-
<string>process.env.INVITATION_FUNDS_SAFE_KEY?.toLowerCase()
423+
<string>this._instanceSpecificInvitationSafeKey.toLowerCase()
394424
);
395425
}
396426

src/jobs/worker/jobWorker.ts

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export abstract class JobWorker<TJob extends JobDescription> {
3636
console.log(`${prefix}[${new Date().toJSON()}] [${Environment.instanceId}] [${jobDescription._topic}] [jobId:${jobId}] [${me.name()}.run]: ${message}`);
3737
}
3838

39+
const start = new Date().getTime();
40+
3941
log(" *-> ", jobDescription.getPayload());
4042

4143
try {
@@ -83,6 +85,10 @@ export abstract class JobWorker<TJob extends JobDescription> {
8385
throw e;
8486
}
8587
}
88+
89+
const duration = new Date().getTime() - start;
90+
log(" <- ", `took ${duration} ms.`)
91+
8692
return {
8793
error: `${error.message + "\n" + error.stack}`
8894
};

0 commit comments

Comments
 (0)