or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context-management.mdindex.mdplugin-orchestration.mdruntime-inspection.mdtimer-coordination.md

timer-coordination.mddocs/

0

# Timer Coordination

1

2

Promise-based timer system with event-driven resolution for scheduling and synchronization in plugin architectures. Provides Clock and Timer classes for managing asynchronous operations, timeouts, and coordination between different parts of the system.

3

4

## Capabilities

5

6

### Clock Class

7

8

Container that manages timer instances and provides access to timing operations. Acts as a central registry for all timers in the system.

9

10

```typescript { .api }

11

/**

12

* Clock manages timer instances and provides timing coordination

13

*/

14

class Clock {

15

/** Internal timer storage (readonly) */

16

readonly store: TimerMap;

17

18

/** Get a timer from the clock by timer type, throws if not found */

19

get(timer: TimerType): Timer;

20

/** Remove a timer from the clock by timer type */

21

remove(timer: TimerType): void;

22

/** Check if the clock has a timer by timer type */

23

has(timer: TimerType): boolean;

24

}

25

```

26

27

**Usage Examples:**

28

29

```typescript

30

import { Clock, createTimer } from "@milkdown/ctx";

31

32

const clock = new Clock();

33

const loadTimer = createTimer("data-load", 5000);

34

35

// Create timer in clock

36

loadTimer.create(clock.store);

37

38

// Check if timer exists

39

if (clock.has(loadTimer)) {

40

const timer = clock.get(loadTimer);

41

console.log("Timer status:", timer.status); // "pending"

42

}

43

44

// Remove timer

45

clock.remove(loadTimer);

46

```

47

48

### Timer Class

49

50

Promise-based timer that can be resolved externally through event dispatching. Supports timeout mechanisms and status tracking.

51

52

```typescript { .api }

53

/**

54

* Timer provides promise-based timing with event-driven resolution

55

*/

56

class Timer {

57

/** The timer type definition (readonly) */

58

readonly type: TimerType;

59

/** Current timer status: pending, resolved, or rejected (readonly) */

60

readonly status: TimerStatus;

61

62

/** Start the timer and return a promise that resolves when done() is called */

63

start(): Promise<void>;

64

/** Resolve the timer by dispatching a custom event */

65

done(): void;

66

}

67

68

type TimerStatus = 'pending' | 'resolved' | 'rejected';

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

import { Clock, createTimer } from "@milkdown/ctx";

75

76

const clock = new Clock();

77

const processTimer = createTimer("process-data", 10000);

78

const timer = processTimer.create(clock.store);

79

80

// Start timer

81

const timerPromise = timer.start();

82

83

console.log("Timer status:", timer.status); // "pending"

84

85

// Resolve timer after some operation

86

setTimeout(() => {

87

timer.done();

88

console.log("Timer status:", timer.status); // "resolved"

89

}, 2000);

90

91

// Wait for completion

92

timerPromise.then(() => {

93

console.log("Timer completed successfully!");

94

}).catch((error) => {

95

console.error("Timer timed out:", error.message);

96

});

97

```

98

99

### TimerType Class

100

101

Type definition for creating timer instances with specified names and timeout durations.

102

103

```typescript { .api }

104

/**

105

* TimerType defines the structure for creating timer instances

106

*/

107

class TimerType {

108

/** Unique identifier for the timer type (readonly) */

109

readonly id: symbol;

110

/** Human-readable timer name (readonly) */

111

readonly name: string;

112

/** Timeout duration in milliseconds (readonly) */

113

readonly timeout: number;

114

115

/** Create a timer type with name and optional timeout (default 3000ms) */

116

constructor(name: string, timeout?: number);

117

/** Create a timer instance in the specified clock */

118

create(clock: TimerMap): Timer;

119

}

120

```

121

122

**Usage Examples:**

123

124

```typescript

125

import { TimerType, Clock } from "@milkdown/ctx";

126

127

// Create timer types with different timeouts

128

const quickTimer = new TimerType("quick-task", 1000);

129

const normalTimer = new TimerType("normal-task", 5000);

130

const longTimer = new TimerType("long-task", 30000);

131

132

const clock = new Clock();

133

134

// Create timer instances

135

const quick = quickTimer.create(clock.store);

136

const normal = normalTimer.create(clock.store);

137

const long = longTimer.create(clock.store);

138

139

console.log("Quick timer timeout:", quick.type.timeout); // 1000

140

console.log("Normal timer timeout:", normal.type.timeout); // 5000

141

console.log("Long timer timeout:", long.type.timeout); // 30000

142

```

143

144

### createTimer Function

145

146

Factory function for creating TimerType instances with cleaner syntax.

147

148

```typescript { .api }

149

/**

150

* Factory function for creating TimerType instances

151

* @param name - Unique name for the timer

152

* @param timeout - Timeout duration in milliseconds (default 3000)

153

* @returns New TimerType instance

154

*/

155

function createTimer(name: string, timeout?: number): TimerType;

156

```

157

158

**Usage Examples:**

159

160

```typescript

161

import { createTimer, Clock } from "@milkdown/ctx";

162

163

// Create various timer types

164

const authTimer = createTimer("authentication", 5000);

165

const apiTimer = createTimer("api-request", 10000);

166

const renderTimer = createTimer("render-complete", 2000);

167

const defaultTimer = createTimer("default-task"); // Uses 3000ms default

168

169

const clock = new Clock();

170

171

// Use in coordination scenarios

172

const timers = [authTimer, apiTimer, renderTimer].map(type =>

173

type.create(clock.store)

174

);

175

176

// Start all timers

177

const promises = timers.map(timer => timer.start());

178

179

// Simulate completion in sequence

180

setTimeout(() => timers[0].done(), 1000); // auth completes

181

setTimeout(() => timers[1].done(), 2000); // api completes

182

setTimeout(() => timers[2].done(), 3000); // render completes

183

184

Promise.all(promises).then(() => {

185

console.log("All operations completed!");

186

});

187

```

188

189

## Advanced Timer Patterns

190

191

### Sequential Timer Coordination

192

193

```typescript

194

import { Clock, createTimer } from "@milkdown/ctx";

195

196

async function sequentialTasks() {

197

const clock = new Clock();

198

199

const tasks = [

200

createTimer("load-config", 2000),

201

createTimer("init-database", 3000),

202

createTimer("start-server", 1000)

203

];

204

205

// Create all timers

206

const timers = tasks.map(task => task.create(clock.store));

207

208

// Execute sequentially

209

for (let i = 0; i < timers.length; i++) {

210

const timer = timers[i];

211

const promise = timer.start();

212

213

// Simulate task completion

214

setTimeout(() => timer.done(), 500 * (i + 1));

215

216

await promise;

217

console.log(`Task ${timer.type.name} completed`);

218

}

219

220

console.log("All tasks completed sequentially");

221

}

222

```

223

224

### Parallel Timer Coordination with Timeout Handling

225

226

```typescript

227

import { Clock, createTimer } from "@milkdown/ctx";

228

229

async function parallelTasksWithTimeouts() {

230

const clock = new Clock();

231

232

const tasks = [

233

createTimer("fast-task", 1000),

234

createTimer("medium-task", 3000),

235

createTimer("slow-task", 5000)

236

];

237

238

const timers = tasks.map(task => task.create(clock.store));

239

const promises = timers.map(timer => timer.start());

240

241

// Simulate different completion times

242

setTimeout(() => timers[0].done(), 500); // fast completes

243

setTimeout(() => timers[1].done(), 2500); // medium completes

244

// slow task will timeout (no done() call)

245

246

// Handle mixed success/timeout results

247

const results = await Promise.allSettled(promises);

248

249

results.forEach((result, index) => {

250

const timerName = timers[index].type.name;

251

if (result.status === 'fulfilled') {

252

console.log(`${timerName} completed successfully`);

253

} else {

254

console.log(`${timerName} timed out:`, result.reason.message);

255

}

256

});

257

}

258

```

259

260

### Timer-Based State Machine

261

262

```typescript

263

import { Clock, createTimer, Container, createSlice } from "@milkdown/ctx";

264

265

type AppState = 'initializing' | 'loading' | 'ready' | 'error';

266

267

class AppStateMachine {

268

private clock = new Clock();

269

private container = new Container();

270

private stateSlice = createSlice<AppState>('initializing', 'app-state');

271

272

constructor() {

273

this.stateSlice.create(this.container.sliceMap);

274

}

275

276

async initialize() {

277

const initTimer = createTimer("initialize", 2000);

278

const timer = initTimer.create(this.clock.store);

279

280

const stateSlice = this.container.get(this.stateSlice);

281

stateSlice.set('initializing');

282

283

// Start initialization

284

const promise = timer.start();

285

286

try {

287

// Simulate initialization work

288

setTimeout(() => {

289

stateSlice.set('loading');

290

timer.done();

291

}, 1000);

292

293

await promise;

294

stateSlice.set('ready');

295

console.log("App initialized successfully");

296

297

} catch (error) {

298

stateSlice.set('error');

299

console.error("Initialization failed:", error);

300

}

301

}

302

303

getState(): AppState {

304

return this.container.get(this.stateSlice);

305

}

306

}

307

```

308

309

## Types

310

311

```typescript { .api }

312

/** Internal type for the clock's timer storage */

313

type TimerMap = Map<symbol, Timer>;

314

315

/** Timer status enumeration */

316

type TimerStatus = 'pending' | 'resolved' | 'rejected';

317

```

318

319

## Error Handling

320

321

The timer system throws specific errors from `@milkdown/exception`:

322

323

- **timerNotFound**: Thrown when attempting to get a timer that doesn't exist in the clock

324

- **Timer timeout**: When timers exceed their timeout duration, promises reject with timeout error

325

326

```typescript

327

import { Clock, createTimer } from "@milkdown/ctx";

328

329

const clock = new Clock();

330

const timer = createTimer("test-timer", 1000);

331

332

try {

333

// This will throw timerNotFound

334

clock.get(timer);

335

} catch (error) {

336

console.error("Timer not found:", error.message);

337

}

338

339

// Timer timeout handling

340

const timeoutTimer = createTimer("timeout-test", 1000);

341

const timerInstance = timeoutTimer.create(clock.store);

342

343

timerInstance.start().catch((error) => {

344

console.error("Timer timed out:", error.message);

345

// Error: "Timing timeout-test timeout."

346

});

347

348

// Don't call timerInstance.done() - let it timeout

349

```

350

351

## Event System Integration

352

353

Timers use the browser's event system for coordination:

354

355

```typescript

356

import { createTimer, Clock } from "@milkdown/ctx";

357

358

const clock = new Clock();

359

const eventTimer = createTimer("custom-event", 5000);

360

const timer = eventTimer.create(clock.store);

361

362

// Listen for timer events directly (advanced usage)

363

addEventListener("custom-event", (event) => {

364

if (event instanceof CustomEvent) {

365

console.log("Timer event received:", event.detail);

366

}

367

});

368

369

// Start timer

370

timer.start().then(() => {

371

console.log("Timer completed via event system");

372

});

373

374

// Resolve timer (triggers custom event)

375

setTimeout(() => timer.done(), 2000);

376

```