or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdtask-queues.mdworker-communication.mdworker-management.md
tile.json

task-queues.mddocs/

0

# Task Queues

1

2

Configurable task scheduling systems that control how method calls are distributed and prioritized across workers. Jest Worker supports pluggable queue implementations to optimize task execution based on different strategies.

3

4

## Capabilities

5

6

### Task Queue Interface

7

8

Base interface for implementing custom task scheduling strategies.

9

10

```typescript { .api }

11

/**

12

* Interface for task queue implementations that manage task distribution

13

*/

14

interface TaskQueue {

15

/**

16

* Enqueue a task for execution by a specific worker or shared queue

17

* @param task - The task to be queued

18

* @param workerId - Optional worker ID for worker-specific tasks

19

*/

20

enqueue(task: QueueChildMessage, workerId?: number): void;

21

22

/**

23

* Dequeue the next task for a specific worker

24

* @param workerId - ID of the worker requesting a task

25

* @returns Next task for the worker or null if none available

26

*/

27

dequeue(workerId: number): QueueChildMessage | null;

28

}

29

30

interface QueueChildMessage {

31

request: ChildMessageCall;

32

onStart: OnStart;

33

onEnd: OnEnd;

34

onCustomMessage: OnCustomMessage;

35

}

36

```

37

38

### FIFO Queue

39

40

First-in, first-out task queue that maintains strict ordering across worker-specific and shared queues. This is the default queue implementation.

41

42

```typescript { .api }

43

/**

44

* First-in, first-out task queue with cross-queue ordering guarantees

45

* Maintains FIFO ordering between worker-specific and shared queues

46

*/

47

class FifoQueue implements TaskQueue {

48

/** Add task to worker-specific or shared queue */

49

enqueue(task: QueueChildMessage, workerId?: number): void;

50

51

/** Get next task for worker, respecting FIFO ordering */

52

dequeue(workerId: number): QueueChildMessage | null;

53

}

54

```

55

56

**Usage Examples:**

57

58

```typescript

59

import { Worker, FifoQueue } from "jest-worker";

60

61

// Default FIFO behavior (no need to specify)

62

const worker = new Worker("./worker.js");

63

64

// Explicitly using FIFO queue

65

const fifoWorker = new Worker("./worker.js", {

66

taskQueue: new FifoQueue()

67

});

68

69

// Tasks are processed in strict order

70

await worker.task1(); // Executed first

71

await worker.task2(); // Executed second

72

await worker.task3(); // Executed third

73

```

74

75

### Priority Queue

76

77

Priority-based task queue that processes tasks according to computed priority values. Lower priority numbers are processed first.

78

79

```typescript { .api }

80

/**

81

* Priority queue that processes tasks by computed priority (lower first)

82

* FIFO ordering is not guaranteed for tasks with the same priority

83

* Worker-specific tasks with same priority as shared tasks are processed first

84

*/

85

class PriorityQueue implements TaskQueue {

86

/**

87

* Create priority queue with custom priority computation

88

* @param computePriority - Function to compute task priority

89

*/

90

constructor(computePriority: ComputeTaskPriorityCallback);

91

92

/** Add task to appropriate priority queue */

93

enqueue(task: QueueChildMessage, workerId?: number): void;

94

95

/** Get highest priority task for worker */

96

dequeue(workerId: number): QueueChildMessage | null;

97

}

98

99

/**

100

* Function to compute priority for tasks

101

* @param method - Name of the method being called

102

* @param args - Arguments passed to the method

103

* @returns Priority number (lower values = higher priority)

104

*/

105

type ComputeTaskPriorityCallback = (

106

method: string,

107

...args: Array<unknown>

108

) => number;

109

```

110

111

**Usage Examples:**

112

113

```typescript

114

import { Worker, PriorityQueue } from "jest-worker";

115

116

// Priority by file size (smaller files first)

117

const fileSizeQueue = new PriorityQueue((method, filepath) => {

118

if (method === "processFile") {

119

const stats = fs.statSync(filepath);

120

return stats.size; // Smaller files = lower priority number = higher priority

121

}

122

return 0; // Default priority for other methods

123

});

124

125

const worker = new Worker("./file-processor.js", {

126

taskQueue: fileSizeQueue

127

});

128

129

// Priority by method importance

130

const methodPriorityQueue = new PriorityQueue((method) => {

131

const priorities = {

132

criticalTask: 1, // Highest priority

133

normalTask: 5, // Medium priority

134

backgroundTask: 10 // Lowest priority

135

};

136

return priorities[method] || 5;

137

});

138

139

const priorityWorker = new Worker("./multi-task-worker.js", {

140

taskQueue: methodPriorityQueue

141

});

142

143

// These will be executed in priority order, not call order

144

await priorityWorker.backgroundTask(); // Priority 10 - executed last

145

await priorityWorker.criticalTask(); // Priority 1 - executed first

146

await priorityWorker.normalTask(); // Priority 5 - executed second

147

```

148

149

### Custom Queue Implementation

150

151

You can implement custom queue strategies by implementing the TaskQueue interface:

152

153

```typescript

154

class CustomQueue implements TaskQueue {

155

private sharedTasks: QueueChildMessage[] = [];

156

private workerTasks: Map<number, QueueChildMessage[]> = new Map();

157

158

enqueue(task: QueueChildMessage, workerId?: number): void {

159

if (workerId !== undefined) {

160

if (!this.workerTasks.has(workerId)) {

161

this.workerTasks.set(workerId, []);

162

}

163

this.workerTasks.get(workerId)!.push(task);

164

} else {

165

this.sharedTasks.push(task);

166

}

167

}

168

169

dequeue(workerId: number): QueueChildMessage | null {

170

// Custom logic: prefer worker-specific tasks on weekends

171

const isWeekend = new Date().getDay() === 0 || new Date().getDay() === 6;

172

173

const workerQueue = this.workerTasks.get(workerId) || [];

174

175

if (isWeekend && workerQueue.length > 0) {

176

return workerQueue.shift() || null;

177

}

178

179

// Otherwise, prefer shared tasks

180

return this.sharedTasks.shift() || workerQueue.shift() || null;

181

}

182

}

183

184

const customWorker = new Worker("./worker.js", {

185

taskQueue: new CustomQueue()

186

});

187

```

188

189

## Queue Behavior Patterns

190

191

### Worker-Specific vs Shared Tasks

192

193

Tasks can be enqueued for specific workers or shared among all workers:

194

195

```typescript

196

// This concept is handled internally by the Farm class

197

// When computeWorkerKey returns a key, tasks are bound to specific workers

198

const boundWorker = new Worker("./caching-worker.js", {

199

computeWorkerKey: (method, key) => {

200

// Tasks with same key always go to same worker

201

return method === "processWithCache" ? key : null;

202

}

203

});

204

205

// These will all go to the same worker (bound by key "user123")

206

await boundWorker.processWithCache("user123", "data1");

207

await boundWorker.processWithCache("user123", "data2");

208

await boundWorker.processWithCache("user123", "data3");

209

```

210

211

### Task Priority Strategies

212

213

Common priority computation patterns:

214

215

```typescript

216

// File size priority (smaller first)

217

const fileSizePriority = (method, filepath) => {

218

return fs.statSync(filepath).size;

219

};

220

221

// String length priority (shorter first)

222

const stringLengthPriority = (method, text) => {

223

return typeof text === "string" ? text.length : 0;

224

};

225

226

// Method-based priority

227

const methodPriority = (method) => {

228

const priorities = { urgent: 1, normal: 5, batch: 10 };

229

return priorities[method] || 5;

230

};

231

232

// Time-based priority (older timestamps first)

233

const timePriority = (method, timestamp) => {

234

return typeof timestamp === "number" ? timestamp : Date.now();

235

};

236

237

// Combined priority strategy

238

const combinedPriority = (method, ...args) => {

239

let priority = methodPriority(method);

240

241

if (method === "processFile" && args[0]) {

242

priority += Math.log(fs.statSync(args[0]).size);

243

}

244

245

return priority;

246

};

247

```

248

249

### Worker Scheduling Policies

250

251

Control how tasks are assigned to idle workers:

252

253

```typescript

254

const worker = new Worker("./worker.js", {

255

workerSchedulingPolicy: "round-robin" // Default: distribute evenly

256

});

257

258

const orderedWorker = new Worker("./worker.js", {

259

workerSchedulingPolicy: "in-order" // Use worker 1 first, then 2, etc.

260

});

261

```

262

263

## Queue Performance Considerations

264

265

### FIFO Queue

266

- **Best for**: Maintaining strict task ordering

267

- **Performance**: O(1) enqueue/dequeue operations

268

- **Memory**: Minimal overhead with linked list structure

269

270

### Priority Queue

271

- **Best for**: Tasks with varying importance levels

272

- **Performance**: O(log n) enqueue/dequeue operations (heap-based)

273

- **Memory**: Higher overhead due to heap maintenance

274

275

### Custom Queues

276

- **Best for**: Specialized scheduling requirements

277

- **Performance**: Depends on implementation

278

- **Memory**: Varies based on data structures used

279

280

Choose the appropriate queue based on your specific use case and performance requirements.