-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
122 lines (108 loc) · 2.99 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import path from "node:path";
import { http, createTestClient, webSocket } from "cive";
import { type ConfluxConfig, ConfluxNode } from "./conflux";
export type Config = {
/**
* show conflux node log
* @default false
*/
log?: boolean;
timeout?: number;
retryInterval?: number;
} & ConfluxConfig;
export type CreateServerReturnType = {
start: () => Promise<void>;
stop: () => Promise<void>;
};
let isServiceCreated = false;
export async function createServer(
config: Config = {},
): Promise<CreateServerReturnType> {
if (isServiceCreated) {
throw new Error("The server has already been created");
}
const { timeout = 20000, retryInterval = 300 } = config;
isServiceCreated = true;
const { log = false, ...userConfig } = config;
const filledConfig: ConfluxConfig = {
posConfigPath: path.join(__dirname, "./configs/pos_config/pos_config.yaml"),
posInitialNodesPath: path.join(
__dirname,
"./configs/pos_config/initial_nodes.json",
),
posPrivateKeyPath: path.join(__dirname, "../configs/pos_config/pos_key"),
logConf: log ? path.join(__dirname, "./configs/log.yaml") : undefined,
...userConfig,
};
const node = new ConfluxNode();
return {
async start() {
await new Promise<void>((resolve, reject) => {
node.startNode(filledConfig, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
if (filledConfig.jsonrpcHttpPort || filledConfig.jsonrpcWsPort) {
await retryGetCurrentSyncPhase({
httpPort: filledConfig.jsonrpcHttpPort,
wsPort: filledConfig.jsonrpcWsPort,
timeout: timeout,
retryInterval: retryInterval,
});
}
},
async stop() {
return new Promise((resolve, reject) => {
node.stopNode((err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
},
};
}
type retryGetCurrentSyncPhaseParameters = {
httpPort?: number;
wsPort?: number;
timeout: number;
retryInterval: number;
};
async function retryGetCurrentSyncPhase({
httpPort,
wsPort,
timeout,
retryInterval,
}: retryGetCurrentSyncPhaseParameters) {
if (!httpPort && !wsPort) return;
const testClient = createTestClient({
transport: httpPort
? http(`http://127.0.0.1:${httpPort}`)
: webSocket(`ws://127.0.0.1:${wsPort}`),
});
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
while (!controller.signal.aborted) {
const phase = await testClient.getCurrentSyncPhase();
if (phase === "NormalSyncPhase") {
clearTimeout(timeoutId);
return;
}
await new Promise((resolve) => setTimeout(resolve, retryInterval));
}
} catch (error) {
if (controller.signal.aborted) {
throw new Error("Get node sync phase timeout");
}
throw error;
} finally {
clearTimeout(timeoutId);
}
}