0
# Sequence Management
1
2
The SequenceClient provides operations for managing sequences (application packages) including starting instances, listing instances, and sequence metadata access.
3
4
## Capabilities
5
6
### Sequence Client Creation
7
8
Create a SequenceClient for managing a specific sequence.
9
10
```typescript { .api }
11
/**
12
* Creates SequenceClient for a specific sequence
13
* @param id - Sequence identifier
14
* @param host - ClientProvider (typically HostClient) for API communication
15
* @returns New SequenceClient instance
16
*/
17
class SequenceClient {
18
readonly id: string;
19
20
static from(id: string, host: ClientProvider): SequenceClient;
21
private constructor(id: string, host: ClientProvider);
22
}
23
```
24
25
**Usage Example:**
26
27
```typescript
28
import { HostClient } from "@scramjet/api-client";
29
30
const host = new HostClient("http://localhost:8000/api/v1");
31
const sequence = host.getSequenceClient("sequence-id");
32
// or
33
const sequence = SequenceClient.from("sequence-id", host);
34
```
35
36
### Instance Management
37
38
Start new instances from the sequence and manage existing ones.
39
40
```typescript { .api }
41
/**
42
* Starts a new instance of the sequence
43
* @param payload - Configuration for starting the sequence
44
* @param payload.appConfig - Application-specific configuration
45
* @param payload.args - Command line arguments to pass to the sequence
46
* @returns Promise resolving to InstanceClient for the started instance
47
* @throws Error if sequence fails to start
48
*/
49
start(payload: STHRestAPI.StartSequencePayload): Promise<InstanceClient>;
50
51
/**
52
* Lists all instances created from this sequence
53
* @returns Promise resolving to array of instance IDs
54
*/
55
listInstances(): Promise<string[]>;
56
57
/**
58
* Gets an InstanceClient for a specific instance
59
* @param id - Instance identifier
60
* @param host - Optional ClientProvider (defaults to sequence's host)
61
* @returns Promise resolving to InstanceClient
62
*/
63
getInstance(id: string, host?: ClientProvider): Promise<InstanceClient>;
64
```
65
66
**Usage Examples:**
67
68
```typescript
69
// Start a sequence with custom configuration
70
const instance = await sequence.start({
71
appConfig: {
72
environment: "production",
73
logLevel: "info"
74
},
75
args: ["--port", "3000", "--verbose"]
76
});
77
78
// Start a sequence with minimal configuration
79
const simpleInstance = await sequence.start({});
80
81
// List all instances of this sequence
82
const instanceIds = await sequence.listInstances();
83
console.log(`Sequence has ${instanceIds.length} instances`);
84
85
// Get a specific instance client
86
const specificInstance = await sequence.getInstance(instanceIds[0]);
87
await specificInstance.sendInput("Hello from sequence management!");
88
```
89
90
### Sequence Information
91
92
Access and modify sequence metadata and configuration.
93
94
```typescript { .api }
95
/**
96
* Gets detailed information about the sequence
97
* @returns Promise resolving to sequence details including configuration and instances
98
*/
99
getInfo(): Promise<STHRestAPI.GetSequenceResponse>;
100
101
/**
102
* Overwrites the sequence with new package data
103
* @param stream - Stream containing the new sequence package
104
* @returns Promise resolving to new SequenceClient for the updated sequence
105
*/
106
overwrite(stream: Readable): Promise<SequenceClient>;
107
```
108
109
**Usage Examples:**
110
111
```typescript
112
import { Readable } from "stream";
113
import fs from "fs";
114
115
// Get sequence information
116
const info = await sequence.getInfo();
117
console.log(`Sequence: ${info.config.name} v${info.config.version}`);
118
console.log(`Active instances: ${info.instances.length}`);
119
120
// Update sequence with new version
121
const newPackageStream = fs.createReadStream("./my-app-v2.tar.gz");
122
const updatedSequence = await sequence.overwrite(newPackageStream);
123
console.log(`Updated sequence ID: ${updatedSequence.id}`);
124
```
125
126
## Configuration Types
127
128
```typescript { .api }
129
interface STHRestAPI {
130
/**
131
* Configuration payload for starting a sequence instance
132
*/
133
StartSequencePayload: {
134
/** Application-specific configuration object */
135
appConfig?: {
136
[key: string]: any;
137
};
138
/** Command line arguments to pass to the sequence */
139
args?: string[];
140
/** Additional configuration options */
141
[key: string]: any;
142
};
143
144
/**
145
* Response containing sequence information
146
*/
147
GetSequenceResponse: {
148
/** Unique sequence identifier */
149
id: string;
150
/** Sequence configuration and metadata */
151
config: {
152
name: string;
153
version: string;
154
description?: string;
155
main?: string;
156
engines?: {
157
node?: string;
158
[key: string]: any;
159
};
160
/** Additional configuration fields */
161
[key: string]: any;
162
};
163
/** List of instance IDs created from this sequence */
164
instances: string[];
165
/** Additional sequence metadata */
166
[key: string]: any;
167
};
168
169
/**
170
* Response when starting a sequence instance
171
*/
172
StartSequenceResponse: {
173
/** ID of the created instance */
174
id: string;
175
/** Instance status */
176
status: "starting" | "running";
177
/** Additional response data */
178
[key: string]: any;
179
};
180
}
181
```
182
183
## Common Patterns
184
185
### Sequential Instance Management
186
187
```typescript
188
// Start multiple instances in sequence
189
const instances: InstanceClient[] = [];
190
191
for (let i = 0; i < 3; i++) {
192
const instance = await sequence.start({
193
appConfig: { workerId: i }
194
});
195
instances.push(instance);
196
197
// Wait for instance to be ready before starting next
198
await instance.getNextEvent("ready");
199
}
200
201
console.log(`Started ${instances.length} instances`);
202
```
203
204
### Instance Pool Management
205
206
```typescript
207
// Manage a pool of instances for load balancing
208
class SequencePool {
209
private instances: InstanceClient[] = [];
210
private currentIndex = 0;
211
212
constructor(private sequence: SequenceClient, private poolSize: number) {}
213
214
async initialize() {
215
for (let i = 0; i < this.poolSize; i++) {
216
const instance = await this.sequence.start({
217
appConfig: { poolIndex: i }
218
});
219
this.instances.push(instance);
220
}
221
}
222
223
getNextInstance(): InstanceClient {
224
const instance = this.instances[this.currentIndex];
225
this.currentIndex = (this.currentIndex + 1) % this.instances.length;
226
return instance;
227
}
228
229
async shutdown() {
230
await Promise.all(
231
this.instances.map(instance => instance.stop(5000, false))
232
);
233
}
234
}
235
236
// Usage
237
const pool = new SequencePool(sequence, 3);
238
await pool.initialize();
239
240
// Process requests using round-robin
241
const instance = pool.getNextInstance();
242
await instance.sendInput(requestData);
243
```
244
245
### Sequence Lifecycle Management
246
247
```typescript
248
// Complete sequence lifecycle from upload to cleanup
249
async function deployAndRunSequence(packagePath: string, config: any) {
250
const host = new HostClient("http://localhost:8000/api/v1");
251
252
// Upload sequence
253
const packageStream = fs.createReadStream(packagePath);
254
const sequence = await host.sendSequence(packageStream);
255
256
try {
257
// Start instance
258
const instance = await sequence.start(config);
259
260
// Wait for completion
261
const result = await instance.getNextEvent("completed");
262
console.log("Sequence completed:", result.data);
263
264
// Graceful shutdown
265
await instance.stop(10000, false);
266
267
} finally {
268
// Clean up sequence
269
await host.deleteSequence(sequence.id, { force: true });
270
}
271
}
272
```
273
274
## Error Handling
275
276
Sequence operations may encounter various error conditions:
277
278
```typescript
279
try {
280
const instance = await sequence.start(config);
281
} catch (error) {
282
if (error.body?.error?.code === 'INSUFFICIENT_RESOURCES') {
283
console.log('Not enough resources to start instance');
284
// Maybe retry later or with different configuration
285
} else if (error.body?.error?.code === 'INVALID_CONFIG') {
286
console.log('Invalid configuration provided:', error.body.error.message);
287
} else {
288
console.log('Failed to start sequence:', error.message);
289
}
290
}
291
292
// Handle instance startup monitoring
293
async function startWithRetry(sequence: SequenceClient, config: any, maxRetries = 3) {
294
for (let attempt = 1; attempt <= maxRetries; attempt++) {
295
try {
296
const instance = await sequence.start(config);
297
298
// Wait for instance to be ready or fail
299
const readyPromise = instance.getNextEvent("ready");
300
const errorPromise = instance.getNextEvent("error");
301
302
const result = await Promise.race([readyPromise, errorPromise]);
303
304
if (result.eventName === "error") {
305
throw new Error(`Instance failed to start: ${result.data}`);
306
}
307
308
return instance;
309
310
} catch (error) {
311
console.log(`Attempt ${attempt} failed:`, error.message);
312
if (attempt === maxRetries) throw error;
313
314
// Wait before retry
315
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
316
}
317
}
318
}
319
```