querysub 0.360.0 → 0.362.0
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/package.json +1 -1
- package/src/deployManager/components/ServiceDetailPage.tsx +72 -1
- package/src/deployManager/components/ServicesListPage.tsx +1 -1
- package/src/deployManager/machineApplyMainCode.ts +50 -0
- package/src/deployManager/machineController.ts +35 -1
- package/src/deployManager/machineSchema.ts +1 -1
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +12 -2
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ import { deepCloneJSON, nextId, sort } from "socket-function/src/misc";
|
|
|
11
11
|
import { InputLabel } from "../../library-components/InputLabel";
|
|
12
12
|
import { Button } from "../../library-components/Button";
|
|
13
13
|
import { isDefined } from "../../misc";
|
|
14
|
-
import { watchScreenOutput, stopWatchingScreenOutput } from "../machineController";
|
|
14
|
+
import { watchScreenOutput, stopWatchingScreenOutput, MachineController } from "../machineController";
|
|
15
15
|
import { getPathStr2 } from "../../path";
|
|
16
16
|
import { ATag, Anchor } from "../../library-components/ATag";
|
|
17
17
|
import { ScrollOnMount } from "../../library-components/ScrollOnMount";
|
|
@@ -38,6 +38,7 @@ export class ServiceDetailPage extends qreact.Component {
|
|
|
38
38
|
data: t.type(""),
|
|
39
39
|
callbackId: t.type(""),
|
|
40
40
|
}),
|
|
41
|
+
isKillingRolling: t.type(false),
|
|
41
42
|
});
|
|
42
43
|
|
|
43
44
|
|
|
@@ -103,6 +104,38 @@ export class ServiceDetailPage extends qreact.Component {
|
|
|
103
104
|
await stopWatchingScreenOutput({ callbackId });
|
|
104
105
|
});
|
|
105
106
|
}
|
|
107
|
+
|
|
108
|
+
private async killAllRollingServices(config: ServiceConfig) {
|
|
109
|
+
Querysub.commit(() => {
|
|
110
|
+
this.state.isKillingRolling = true;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
Querysub.onCommitFinished(async () => {
|
|
114
|
+
try {
|
|
115
|
+
let uniqueMachineIds = Array.from(new Set(config.machineIds));
|
|
116
|
+
|
|
117
|
+
for (let machineId of uniqueMachineIds) {
|
|
118
|
+
let machineInfo = await MachineServiceController(SocketFunction.browserNodeId()).getMachineInfo.promise(machineId);
|
|
119
|
+
if (!machineInfo) continue;
|
|
120
|
+
|
|
121
|
+
let applyNodeId = machineInfo.applyNodeId;
|
|
122
|
+
await MachineController(SocketFunction.browserNodeId()).killRollingServicesFromBrowser.promise({
|
|
123
|
+
machineNodeId: applyNodeId,
|
|
124
|
+
serviceKey: config.parameters.key,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
} catch (e: any) {
|
|
128
|
+
Querysub.localCommit(() => {
|
|
129
|
+
this.state.saveError = `Error killing rolling services: ${e.message}`;
|
|
130
|
+
});
|
|
131
|
+
} finally {
|
|
132
|
+
Querysub.localCommit(() => {
|
|
133
|
+
this.state.isKillingRolling = false;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
106
139
|
private async updateConfig(updatedConfig: ServiceConfig): Promise<void> {
|
|
107
140
|
const selectedServiceId = selectedServiceIdParam.value;
|
|
108
141
|
if (!selectedServiceId) return;
|
|
@@ -151,6 +184,28 @@ export class ServiceDetailPage extends qreact.Component {
|
|
|
151
184
|
const configT = config;
|
|
152
185
|
const hasUnsavedChanges = !!this.state.unsavedChanges;
|
|
153
186
|
|
|
187
|
+
let rollingServiceCount = 0;
|
|
188
|
+
if (config.parameters.rollingWindow) {
|
|
189
|
+
let uniqueMachineIds = Array.from(new Set(config.machineIds));
|
|
190
|
+
for (let machineId of uniqueMachineIds) {
|
|
191
|
+
try {
|
|
192
|
+
let machineInfo = controller.getMachineInfo(machineId);
|
|
193
|
+
if (!machineInfo) continue;
|
|
194
|
+
|
|
195
|
+
let applyNodeId = machineInfo.applyNodeId;
|
|
196
|
+
let rollingInfo = MachineController(SocketFunction.browserNodeId()).getRollingServiceInfoFromBrowser({
|
|
197
|
+
machineNodeId: applyNodeId,
|
|
198
|
+
serviceKey: config.parameters.key,
|
|
199
|
+
});
|
|
200
|
+
if (rollingInfo) {
|
|
201
|
+
rollingServiceCount += rollingInfo.length;
|
|
202
|
+
}
|
|
203
|
+
} catch (e: any) {
|
|
204
|
+
console.error(`Error getting rolling service info for machine ${machineId}: ${e.message}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
154
209
|
// Sort machines by status and heartbeat
|
|
155
210
|
let nextIndexes = new Map<string, number>();
|
|
156
211
|
let machineStatuses = config.machineIds.map(machineId => {
|
|
@@ -432,6 +487,22 @@ export class ServiceDetailPage extends qreact.Component {
|
|
|
432
487
|
Poke
|
|
433
488
|
</button>
|
|
434
489
|
|
|
490
|
+
{configT.parameters.rollingWindow && rollingServiceCount > 0 && <button
|
|
491
|
+
className={css.pad2(12, 8).button.bord2(0, 0, 20).hsl(0, 70, 90)}
|
|
492
|
+
onClick={() => {
|
|
493
|
+
void this.killAllRollingServices(config);
|
|
494
|
+
}}
|
|
495
|
+
disabled={this.state.isKillingRolling}
|
|
496
|
+
>
|
|
497
|
+
{this.state.isKillingRolling ? "Killing..." : `💀 Kill ${rollingServiceCount} Rolling Service${rollingServiceCount === 1 ? "" : "s"}`}
|
|
498
|
+
</button>}
|
|
499
|
+
|
|
500
|
+
{configT.parameters.rollingWindow && <div>
|
|
501
|
+
<div className={css.colorhsl(0, 50, 50).fontSize(14).fontWeight("bold")}>
|
|
502
|
+
IMPORTANT! Service has a rolling window, so updates might not appear immediately.
|
|
503
|
+
</div>
|
|
504
|
+
</div>}
|
|
505
|
+
|
|
435
506
|
{hasUnsavedChanges && <>
|
|
436
507
|
<Button
|
|
437
508
|
flavor="noui"
|
|
@@ -136,7 +136,7 @@ export class ServicesListPage extends qreact.Component {
|
|
|
136
136
|
</div>
|
|
137
137
|
<div className={css.vbox(4)}>
|
|
138
138
|
<div>Updated {formatDateJSX(config.info.lastUpdatedTime)} AGO</div>
|
|
139
|
-
{config.parameters.rollingWindow && <div>Rolling window: {formatTime(config.parameters.rollingWindow)}</div> || undefined}
|
|
139
|
+
{config.parameters.rollingWindow && <div className={css.colorhsl(0, 50, 50).fontSize(14).fontWeight("bold")}>Rolling window: {formatTime(config.parameters.rollingWindow)}</div> || undefined}
|
|
140
140
|
</div>
|
|
141
141
|
</div>
|
|
142
142
|
</Anchor>
|
|
@@ -265,6 +265,45 @@ done`);
|
|
|
265
265
|
})();
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
export async function getRollingServiceInfo(config: {
|
|
269
|
+
serviceKey: string;
|
|
270
|
+
}): Promise<{ rollingScreenName: string; originalScreenName: string; expiresAt: number }[]> {
|
|
271
|
+
let rollingInfo: { rollingScreenName: string; originalScreenName: string; expiresAt: number }[] = [];
|
|
272
|
+
|
|
273
|
+
for (let [screenName, rolling] of rollingKeepScreenAlive) {
|
|
274
|
+
if (screenName.startsWith(config.serviceKey + "-")) {
|
|
275
|
+
rollingInfo.push({
|
|
276
|
+
rollingScreenName: rolling.rollingScreenName,
|
|
277
|
+
originalScreenName: rolling.originalScreenName,
|
|
278
|
+
expiresAt: rolling.pinnedTime + rolling.pinnedDuration,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return rollingInfo;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export async function killRollingServicesForService(config: {
|
|
287
|
+
serviceKey: string;
|
|
288
|
+
}): Promise<void> {
|
|
289
|
+
let toDelete: string[] = [];
|
|
290
|
+
|
|
291
|
+
for (let [screenName, rolling] of rollingKeepScreenAlive) {
|
|
292
|
+
if (screenName.startsWith(config.serviceKey + "-")) {
|
|
293
|
+
console.log(red(`Explicitly killing rolling screen ${rolling.rollingScreenName} for service ${config.serviceKey}`));
|
|
294
|
+
await killScreen({
|
|
295
|
+
screenName: rolling.rollingScreenName,
|
|
296
|
+
});
|
|
297
|
+
rollingScreens.delete(rolling.rollingScreenName);
|
|
298
|
+
toDelete.push(screenName);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
for (let screenName of toDelete) {
|
|
303
|
+
rollingKeepScreenAlive.delete(screenName);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
268
307
|
|
|
269
308
|
const getTmuxPrefix = lazy(() => {
|
|
270
309
|
if (os.platform() === "win32") {
|
|
@@ -734,6 +773,17 @@ const resyncServicesBase = runInSerial(measureWrap(async function resyncServices
|
|
|
734
773
|
continue;
|
|
735
774
|
}
|
|
736
775
|
}
|
|
776
|
+
|
|
777
|
+
let rollingInfo = rollingKeepScreenAlive.get(screenName);
|
|
778
|
+
if (rollingInfo) {
|
|
779
|
+
console.log(red(`Service ${screenName} was disabled, killing associated rolling screen ${rollingInfo.rollingScreenName}`));
|
|
780
|
+
await killScreen({
|
|
781
|
+
screenName: rollingInfo.rollingScreenName,
|
|
782
|
+
});
|
|
783
|
+
rollingScreens.delete(rollingInfo.rollingScreenName);
|
|
784
|
+
rollingKeepScreenAlive.delete(screenName);
|
|
785
|
+
}
|
|
786
|
+
|
|
737
787
|
await killScreen({
|
|
738
788
|
screenName,
|
|
739
789
|
});
|
|
@@ -5,7 +5,7 @@ import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
|
|
|
5
5
|
import { timeInMinute } from "socket-function/src/misc";
|
|
6
6
|
import { assertIsManagementUser } from "../diagnostics/managementPages";
|
|
7
7
|
import { isNode } from "typesafecss";
|
|
8
|
-
import { streamScreenOutput } from "./machineApplyMainCode";
|
|
8
|
+
import { streamScreenOutput, getRollingServiceInfo, killRollingServicesForService } from "./machineApplyMainCode";
|
|
9
9
|
import { Querysub } from "../4-querysub/QuerysubController";
|
|
10
10
|
import { getPathStr2 } from "../path";
|
|
11
11
|
import { getGitURLLive, setGitRef } from "../4-deploy/git";
|
|
@@ -140,6 +140,36 @@ class MachineControllerBase {
|
|
|
140
140
|
await runPromise("bash machine-startup.sh", { cwd: os.homedir(), detach: true });
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
public async getRollingServiceInfo(config: {
|
|
144
|
+
serviceKey: string;
|
|
145
|
+
}): Promise<{ rollingScreenName: string; originalScreenName: string; expiresAt: number }[]> {
|
|
146
|
+
return await getRollingServiceInfo(config);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public async getRollingServiceInfoFromBrowser(config: {
|
|
150
|
+
machineNodeId: string;
|
|
151
|
+
serviceKey: string;
|
|
152
|
+
}): Promise<{ rollingScreenName: string; originalScreenName: string; expiresAt: number }[]> {
|
|
153
|
+
return await MachineController(config.machineNodeId).getRollingServiceInfo.promise({
|
|
154
|
+
serviceKey: config.serviceKey,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public async killRollingServices(config: {
|
|
159
|
+
serviceKey: string;
|
|
160
|
+
}): Promise<void> {
|
|
161
|
+
await killRollingServicesForService(config);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public async killRollingServicesFromBrowser(config: {
|
|
165
|
+
machineNodeId: string;
|
|
166
|
+
serviceKey: string;
|
|
167
|
+
}): Promise<void> {
|
|
168
|
+
await MachineController(config.machineNodeId).killRollingServices.promise({
|
|
169
|
+
serviceKey: config.serviceKey,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
143
173
|
}
|
|
144
174
|
|
|
145
175
|
let forwardedCallbacks = new Map<string, string>();
|
|
@@ -152,6 +182,10 @@ export const MachineController = getSyncedController(SocketFunction.register(
|
|
|
152
182
|
watchOtherScreenOutput: {},
|
|
153
183
|
deployMachineFromBrowser: {},
|
|
154
184
|
deployMachine: {},
|
|
185
|
+
getRollingServiceInfo: {},
|
|
186
|
+
getRollingServiceInfoFromBrowser: {},
|
|
187
|
+
killRollingServices: {},
|
|
188
|
+
killRollingServicesFromBrowser: {},
|
|
155
189
|
}),
|
|
156
190
|
() => ({
|
|
157
191
|
hooks: [assertIsManagementUser],
|
|
@@ -33,7 +33,7 @@ export const SERVICE_NODE_FILE_NAME = "serviceNodeId.txt";
|
|
|
33
33
|
export type MachineInfo = {
|
|
34
34
|
machineId: string;
|
|
35
35
|
|
|
36
|
-
// Used to
|
|
36
|
+
// Used to talk to the apply script directly (ex, recheck the service config, kill the rolling nodes, etc)
|
|
37
37
|
applyNodeId: string;
|
|
38
38
|
|
|
39
39
|
heartbeat: number;
|
|
@@ -19,7 +19,17 @@ IMPORTANT! Now I am properly calling shutdown, so none of the streamed logs shou
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
BUG: We aren't able to connect directly to the apply service? Hmm...
|
|
23
|
+
|
|
24
|
+
0) Make a minor UI change, so we can see rolling nodes appear
|
|
25
|
+
1) Disable, to ensure rolling nodes go away
|
|
26
|
+
2) Re-enable
|
|
27
|
+
3) Another minor UI change
|
|
28
|
+
4) Use the new "kill rolling" so we can see a forced update
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
BUG: Why are CYOA deploys not working!
|
|
32
|
+
I even disabled it, and nothing. It's still running. WTF...
|
|
23
33
|
|
|
24
34
|
Hmm... why are not enough logs appearing?
|
|
25
35
|
- We only have logs for server.ts? Wtf?
|
|
@@ -34,7 +44,7 @@ Hmm... why are not enough logs appearing?
|
|
|
34
44
|
- Basically, just changes the code we're reading from multiple servers to select public servers instead, and then, of course, skip ourselves.
|
|
35
45
|
|
|
36
46
|
BUG: UGH... live logs for the remote server isn't working...
|
|
37
|
-
|
|
47
|
+
new non-local WATCH
|
|
38
48
|
- UGH... it being pending logs is annoying, as that's hard to debug locally...
|
|
39
49
|
AH! Why do we have so few logs?
|
|
40
50
|
|