Skip to content

Commit d478c09

Browse files
committed
fix(upload-contract): prevent race condition when restarting ag-solo
Also, only upload contracts if we haven't already initialized.
1 parent dab8b3a commit d478c09

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

lib/ag-solo/start.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export default async function start(basedir, withSES, argv) {
207207

208208
if (pairs.length > 0) {
209209
// eslint-disable-next-line no-await-in-loop
210-
await uploadContract(basedir, pairs);
210+
await uploadContract(basedir, ['--once', ...pairs]);
211211
}
212212
}
213213
}

lib/ag-solo/upload-contract.js

+22-12
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ const sendJSON = (ws, obj) => {
2626
};
2727

2828
export default async function upload(basedir, args) {
29-
const { _: namePaths, 'ag-solo': agSolo } = parseArgs(args, {
29+
const { _: namePaths, once, 'ag-solo': agSolo } = parseArgs(args, {
30+
boolean: ['once'],
3031
default: {
3132
target: 'contractHost',
3233
},
@@ -37,8 +38,6 @@ export default async function upload(basedir, args) {
3738
return 1;
3839
}
3940

40-
console.log(`Uploading contracts...`);
41-
4241
let wsurl = agSolo;
4342
if (!agSolo) {
4443
const cjson = await fs.promises.readFile(
@@ -77,9 +76,20 @@ export default async function upload(basedir, args) {
7776
console.log('Chain loaded:', await bootC.G.LOADING.P);
7877
// Take a new copy, since the contract targets should exist.
7978
bootC = E.C(bootstrap());
79+
if (once) {
80+
if (await bootC.G.READY.M.isReady().P) {
81+
console.log('Contracts already uploaded');
82+
ws.close();
83+
exit.res(0);
84+
return;
85+
}
86+
}
87+
const uploadsC = bootC.G.uploads;
88+
89+
console.log(`Uploading contracts...`);
8090

81-
const contractAP = [];
8291
const names = [];
92+
const contractsAP = [];
8393
for (const namePath of namePaths) {
8494
const match = namePath.match(/^(([^\W-]+)-[^=]+)=(.+)$/);
8595
if (!match) {
@@ -98,21 +108,21 @@ export default async function upload(basedir, args) {
98108
);
99109
} else {
100110
// Install the contract, then save it in home.uploads.
101-
contractAP.push(E(targetObj).install(source, moduleFormat));
111+
console.log(`Uploading ${name}`)
112+
contractsAP.push(E(targetObj).install(source, moduleFormat));
102113
names.push(name);
103114
}
104115
}
105116

106-
const contracts = await Promise.all(contractAP);
107-
108-
const uploadsC = bootC.G.uploads;
109-
const uploadAP = [];
110-
for (let i = 0; i < contractAP.length; i += 1) {
111-
uploadAP.push(uploadsC.M.set(names[i], contracts[i]).P);
117+
const contracts = await Promise.all(contractsAP);
118+
for (let i = 0; i < contracts.length; i ++) {
119+
await uploadsC.M.set(names[i], contracts[i]).P;
112120
}
113121

114-
await Promise.all(uploadAP);
115122
console.log('Success! See home.uploads~.list()');
123+
if (once) {
124+
await bootC.G.READY.M.resolve('contracts uploaded').P;
125+
}
116126
ws.close();
117127
exit.res(0);
118128
} catch (e) {

lib/ag-solo/vats/vat-http.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,21 @@ function build(E, D) {
1414
});
1515
harden(loaded);
1616
const homeObjects = { LOADING: loaded.p };
17-
let exportedToCapTP = { LOADING: loaded.p };
17+
let isReady = false;
18+
let exportedToCapTP = {
19+
LOADING: loaded.p,
20+
READY: {
21+
resolve(value) { isReady = true; readyForClient.res(value); },
22+
isReady() { return isReady; },
23+
},
24+
};
25+
26+
const readyForClient = {};
27+
readyForClient.p = new Promise((resolve, reject) => {
28+
readyForClient.res = resolve;
29+
readyForClient.rej = reject;
30+
});
31+
harden(readyForClient);
1832

1933
let handler = {};
2034
let canvasState;
@@ -51,6 +65,11 @@ function build(E, D) {
5165
getReplHandler(E, homeObjects, msg =>
5266
D(commandDevice).sendBroadcast(msg),
5367
),
68+
{
69+
readyForClient() {
70+
return readyForClient.p;
71+
},
72+
},
5473
{
5574
CTP_OPEN(obj) {
5675
console.log(`Starting CapTP`, obj.connectionID);
@@ -96,7 +115,7 @@ function build(E, D) {
96115
},
97116

98117
setPresences(ps, privateObjects) {
99-
exportedToCapTP = { ...ps, ...privateObjects };
118+
exportedToCapTP = { READY: exportedToCapTP.READY, ...ps, ...privateObjects };
100119
Object.assign(homeObjects, ps, privateObjects);
101120
loaded.res('chain bundle loaded');
102121
if (ps.canvasStatePublisher) {

0 commit comments

Comments
 (0)