querysub 0.530.0 → 0.532.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.530.0",
3
+ "version": "0.532.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",
@@ -71,7 +71,7 @@
71
71
  "node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
72
72
  "pako": "^2.1.0",
73
73
  "peggy": "^5.0.6",
74
- "sliftutils": "^1.7.13",
74
+ "sliftutils": "^1.7.15",
75
75
  "socket-function": "^1.2.21",
76
76
  "terser": "^5.31.0",
77
77
  "typenode": "^6.6.1",
@@ -59,7 +59,7 @@ export class ArchivesBackblaze {
59
59
  public async get2(fileName: string, config?: { range?: { start: number; end: number; } }): Promise<{ data: Buffer; writeTime: number; size: number } | undefined> {
60
60
  return this.archives.get2(fileName, config);
61
61
  }
62
- public async set(fileName: string, data: Buffer, config?: { lastModified?: number }): Promise<void> {
62
+ public async set(fileName: string, data: Buffer, config?: { lastModified?: number }): Promise<string> {
63
63
  return this.archives.set(fileName, data, config);
64
64
  }
65
65
  public async append(fileName: string, data: Buffer): Promise<void> {
@@ -141,7 +141,19 @@ export class ServicesListPage extends qreact.Component {
141
141
  </div>
142
142
  <div className={css.vbox(4)}>
143
143
  <div>Updated {formatDateJSX(config.info.lastUpdatedTime)} AGO</div>
144
- {config.parameters.overlapTime && <div className={css.colorhsl(210, 50, 50).fontSize(14).fontWeight("bold")}>Deploy overlap: {formatTime(config.parameters.overlapTime)}</div> || undefined}
144
+ {(() => {
145
+ // The old instances probably still run out their overlap (purely time-based, we don't verify they're actually running)
146
+ let releaseTime = config.parameters.releaseTime || 0;
147
+ let overlapTime = config.parameters.overlapTime ?? DEFAULT_OVERLAP_TIME;
148
+ if (!releaseTime || !config.oldParameters) return undefined;
149
+ if (now < releaseTime || now >= releaseTime + overlapTime) return undefined;
150
+ return <div
151
+ className={css.colorhsl(280, 60, 45).fontSize(14).fontWeight("bold")}
152
+ title={`Old instances shut down at ${formatDateTimeDetailed(releaseTime + overlapTime)}`}
153
+ >
154
+ 🔀 Old version still running for {formatTime(releaseTime + overlapTime - now)}
155
+ </div>;
156
+ })()}
145
157
  {(() => {
146
158
  let releaseTime = config.parameters.releaseTime || 0;
147
159
  if (!releaseTime || releaseTime <= now || !config.oldParameters) return undefined;
@@ -46,18 +46,21 @@ export class UpdateButtons extends qreact.Component<{
46
46
  state = t.state({
47
47
  isDeploying: t.type(false),
48
48
  });
49
- // Deploys all outdated services to latestRef. Scheduled releases delay the release by the configured overlap (an unrelated value, but a reasonable delay); immediate releases right away.
50
- private deployAll(outdatedServices: ServiceConfig[], latestRef: string, immediate: boolean) {
49
+ // Deploys all outdated services to latestRef. "scheduled" delays the release by the configured overlap (an unrelated value, but a reasonable delay); "now" releases immediately but the old instances still run out their configured overlap; "nowNoOverlap" releases immediately AND shuts the old instances down immediately.
50
+ private deployAll(outdatedServices: ServiceConfig[], latestRef: string, mode: "scheduled" | "now" | "nowNoOverlap") {
51
51
  this.state.isDeploying = true;
52
52
  // Props are synchronized state, so everything the async work needs is cloned into plain locals HERE, in the synced part
53
53
  let toDeploy = outdatedServices.map(service => {
54
54
  let updated = deepCloneJSON(service);
55
55
  updated.parameters.gitRef = latestRef;
56
- if (immediate) {
57
- updated.parameters.releaseTime = undefined;
58
- } else {
56
+ if (mode === "scheduled") {
59
57
  let overlap = updated.parameters.overlapTime ?? DEFAULT_OVERLAP_TIME;
60
58
  updated.parameters.releaseTime = Date.now() + overlap;
59
+ } else {
60
+ updated.parameters.releaseTime = Date.now();
61
+ if (mode === "nowNoOverlap") {
62
+ updated.parameters.overlapTime = 0;
63
+ }
61
64
  }
62
65
  return updated;
63
66
  });
@@ -72,6 +75,32 @@ export class UpdateButtons extends qreact.Component<{
72
75
  }
73
76
  });
74
77
  }
78
+ private confirmDeployAllNow(outdatedServices: ServiceConfig[], latestRef: string, noOverlap: boolean) {
79
+ let modal: { close: () => void } | undefined;
80
+ modal = showFullscreenModal({
81
+ content: <div className={css.vbox(12).pad2(20)}>
82
+ <div className={css.boldStyle.fontSize(16)}>⚡ Deploy all {outdatedServices.length} services now?</div>
83
+ <div>{noOverlap
84
+ ? "All services release immediately AND their old instances shut down immediately (overlap of 0)."
85
+ : "All services release immediately. Their old instances keep running for their configured overlap before shutting down."}</div>
86
+ <div className={css.hbox(10)}>
87
+ <button
88
+ className={css.pad2(12, 8).button.bord2(0, 70, 40).hsl(0, 70, 90)}
89
+ onClick={() => {
90
+ modal && modal.close();
91
+ this.deployAll(outdatedServices, latestRef, noOverlap ? "nowNoOverlap" : "now");
92
+ }}>
93
+ ⚡ Deploy Now
94
+ </button>
95
+ <button
96
+ className={css.pad2(12, 8).button.bord2(0, 0, 20).hsl(0, 0, 100)}
97
+ onClick={() => modal && modal.close()}>
98
+ Cancel
99
+ </button>
100
+ </div>
101
+ </div>
102
+ });
103
+ }
75
104
  render() {
76
105
  let controller = MachineServiceController(SocketFunction.browserNodeId());
77
106
  const gitInfo = controller.getGitInfo();
@@ -129,7 +158,7 @@ export class UpdateButtons extends qreact.Component<{
129
158
  className={buttonStyle.hsl(120, 70, 90)}
130
159
  disabled={this.state.isDeploying}
131
160
  onClick={() => {
132
- this.deployAll(outdatedServices, gitInfo.latestRef, false);
161
+ this.deployAll(outdatedServices, gitInfo.latestRef, "scheduled");
133
162
  }}
134
163
  >
135
164
  <div>
@@ -147,15 +176,27 @@ export class UpdateButtons extends qreact.Component<{
147
176
  <button
148
177
  className={buttonStyle.hsl(0, 70, 90)}
149
178
  disabled={this.state.isDeploying}
150
- title="Deploys immediately, with no overlap: the old instances are shut down right away"
179
+ title="Deploys immediately; the old instances keep running for their configured overlap before shutting down"
151
180
  onClick={() => {
152
- this.deployAll(outdatedServices, gitInfo.latestRef, true);
181
+ this.confirmDeployAllNow(outdatedServices, gitInfo.latestRef, false);
153
182
  }}
154
183
  >
155
184
  <div>
156
185
  {bigEmoji("⚡")} <span>{this.state.isDeploying && "⏳ Deploying..." || `Deploy All (${outdatedServices.length}) Now (no delay)`}</span>
157
186
  </div>
158
187
  </button>
188
+ <button
189
+ className={buttonStyle.hsl(0, 85, 70)}
190
+ disabled={this.state.isDeploying}
191
+ title="Deploys immediately AND shuts down the old instances immediately (overlap of 0)"
192
+ onClick={() => {
193
+ this.confirmDeployAllNow(outdatedServices, gitInfo.latestRef, true);
194
+ }}
195
+ >
196
+ <div>
197
+ {bigEmoji("⚡")} <span>{this.state.isDeploying && "⏳ Deploying..." || `Deploy All (${outdatedServices.length}) Now (no delay, no overlap)`}</span>
198
+ </div>
199
+ </button>
159
200
  </>}
160
201
  </>;
161
202
  }