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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.360.0",
3
+ "version": "0.362.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
@@ -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 tell the apply tool to update it's configs now
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
- Logs still aren't appearing. Hmm...
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
- "new non-local WATCH"
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