or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdcomponents.mdcontext-api.mdextensions.mdindex.mdlifecycle.mdservices.md

lifecycle.mddocs/

0

# Lifecycle Management

1

2

LoopBack Core provides comprehensive lifecycle management for coordinating application startup and shutdown sequences. The system ensures that all components, servers, and services are initialized, started, and stopped in the correct order with proper dependency management.

3

4

## Capabilities

5

6

### LifeCycleObserver Interface

7

8

Core interface for implementing lifecycle-aware components that need to participate in application startup and shutdown sequences.

9

10

```typescript { .api }

11

/**

12

* Observers to handle life cycle init/start/stop events

13

*/

14

interface LifeCycleObserver {

15

/** The method to be invoked during init. Called at most once per application instance. */

16

init?(...injectedArgs: unknown[]): ValueOrPromise<void>;

17

18

/** The method to be invoked during start */

19

start?(...injectedArgs: unknown[]): ValueOrPromise<void>;

20

21

/** The method to be invoked during stop */

22

stop?(...injectedArgs: unknown[]): ValueOrPromise<void>;

23

}

24

```

25

26

**Usage Examples:**

27

28

```typescript

29

import { LifeCycleObserver, inject } from "@loopback/core";

30

31

class DatabaseObserver implements LifeCycleObserver {

32

constructor(

33

@inject('datasources.db') private datasource: DataSource,

34

@inject('config.database') private config: DatabaseConfig

35

) {}

36

37

async init(): Promise<void> {

38

console.log('Initializing database connection...');

39

await this.datasource.connect();

40

}

41

42

async start(): Promise<void> {

43

console.log('Database connection ready');

44

await this.runMigrations();

45

}

46

47

async stop(): Promise<void> {

48

console.log('Closing database connection...');

49

await this.datasource.disconnect();

50

}

51

52

private async runMigrations(): Promise<void> {

53

if (this.config.autoMigrate) {

54

// Run database migrations

55

}

56

}

57

}

58

```

59

60

### Lifecycle Observer Decorator

61

62

Decorator for marking classes as lifecycle observers with optional group assignment and binding specifications.

63

64

```typescript { .api }

65

/**

66

* Sugar decorator to mark a class as life cycle observer

67

*/

68

function lifeCycleObserver(group?: string, ...specs: BindingSpec[]): ClassDecorator;

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

import { lifeCycleObserver, LifeCycleObserver, BindingScope } from "@loopback/core";

75

76

// Basic lifecycle observer

77

@lifeCycleObserver()

78

class CacheObserver implements LifeCycleObserver {

79

async start(): Promise<void> {

80

console.log('Cache warming up...');

81

}

82

83

async stop(): Promise<void> {

84

console.log('Cache shutting down...');

85

}

86

}

87

88

// Observer with group assignment

89

@lifeCycleObserver('database')

90

class DatabaseObserver implements LifeCycleObserver {

91

async init(): Promise<void> {

92

console.log('Database initializing...');

93

}

94

}

95

96

// Observer with binding specifications

97

@lifeCycleObserver('server', {scope: BindingScope.SINGLETON})

98

class ServerObserver implements LifeCycleObserver {

99

async start(): Promise<void> {

100

console.log('Server starting...');

101

}

102

}

103

104

// Observer with multiple specifications

105

@lifeCycleObserver('external-services',

106

{scope: BindingScope.SINGLETON},

107

{tags: {priority: 'high'}}

108

)

109

class ExternalServiceObserver implements LifeCycleObserver {

110

async init(): Promise<void> {

111

console.log('Connecting to external services...');

112

}

113

}

114

```

115

116

### Lifecycle Utility Functions

117

118

Helper functions for working with lifecycle observers and bindings.

119

120

```typescript { .api }

121

/**

122

* Test if an object implements LifeCycleObserver

123

*/

124

function isLifeCycleObserver(obj: object): obj is LifeCycleObserver;

125

126

/**

127

* Test if a class implements LifeCycleObserver

128

*/

129

function isLifeCycleObserverClass(

130

ctor: Constructor<unknown>

131

): ctor is Constructor<LifeCycleObserver>;

132

133

/**

134

* A BindingTemplate function to configure the binding as life cycle observer

135

* by tagging it with CoreTags.LIFE_CYCLE_OBSERVER.

136

*/

137

function asLifeCycleObserver<T = unknown>(binding: Binding<T>): Binding<T>;

138

139

/**

140

* Find all life cycle observer bindings. By default, a binding tagged with

141

* CoreTags.LIFE_CYCLE_OBSERVER. Used as BindingFilter.

142

*/

143

const lifeCycleObserverFilter: BindingTagFilter;

144

```

145

146

**Usage Examples:**

147

148

```typescript

149

import {

150

isLifeCycleObserver,

151

isLifeCycleObserverClass,

152

asLifeCycleObserver,

153

lifeCycleObserverFilter,

154

LifeCycleObserver

155

} from "@loopback/core";

156

157

// Check if object implements lifecycle observer

158

const service = new MyService();

159

if (isLifeCycleObserver(service)) {

160

await service.start?.();

161

}

162

163

// Check if class implements lifecycle observer

164

class MyObserver implements LifeCycleObserver {

165

async start(): Promise<void> {}

166

}

167

168

if (isLifeCycleObserverClass(MyObserver)) {

169

console.log('MyObserver implements LifeCycleObserver');

170

}

171

172

// Configure binding as lifecycle observer

173

const binding = context.bind('my-observer')

174

.toClass(MyObserver)

175

.apply(asLifeCycleObserver);

176

177

// Find all lifecycle observer bindings

178

const observerBindings = context.find(lifeCycleObserverFilter);

179

```

180

181

### LifeCycleObserverRegistry

182

183

Central registry that manages and coordinates lifecycle observers with support for grouping, ordering, and parallel execution.

184

185

```typescript { .api }

186

/**

187

* A context-based registry for life cycle observers

188

*/

189

class LifeCycleObserverRegistry implements LifeCycleObserver {

190

constructor(

191

context: Context,

192

observersView: ContextView<LifeCycleObserver>,

193

options?: LifeCycleObserverOptions

194

);

195

196

/** Set the ordered groups for observer execution */

197

setOrderedGroups(groups: string[]): void;

198

199

/** Get observer groups ordered by the group configuration */

200

getObserverGroupsByOrder(): LifeCycleObserverGroup[];

201

202

/** Notify all life cycle observers by group of init */

203

init(): Promise<void>;

204

205

/** Notify all life cycle observers by group of start */

206

start(): Promise<void>;

207

208

/** Notify all life cycle observers by group of stop */

209

stop(): Promise<void>;

210

}

211

```

212

213

**Usage Examples:**

214

215

```typescript

216

import {

217

LifeCycleObserverRegistry,

218

LifeCycleObserverOptions,

219

DEFAULT_ORDERED_GROUPS

220

} from "@loopback/core";

221

222

// Custom registry configuration

223

const options: LifeCycleObserverOptions = {

224

orderedGroups: ['database', 'cache', 'server'],

225

disabledGroups: ['optional-services'],

226

parallel: true

227

};

228

229

// Manual registry usage (typically handled by Application)

230

const registry = new LifeCycleObserverRegistry(

231

context,

232

observersView,

233

options

234

);

235

236

// Set custom ordering

237

registry.setOrderedGroups(['datasource', 'server', 'monitoring']);

238

239

// Get ordered groups

240

const groups = registry.getObserverGroupsByOrder();

241

console.log('Observer groups:', groups.map(g => g.group));

242

243

// Manual lifecycle management

244

await registry.init();

245

await registry.start();

246

await registry.stop();

247

```

248

249

### Lifecycle Observer Options

250

251

Configuration interface for controlling how lifecycle observers are executed.

252

253

```typescript { .api }

254

interface LifeCycleObserverOptions {

255

/** Control the order of observer groups for notifications */

256

orderedGroups: string[];

257

258

/** Override and disable lifecycle observer groups */

259

disabledGroups?: string[];

260

261

/** Notify observers of the same group in parallel, default to true */

262

parallel?: boolean;

263

}

264

265

/** Default ordered groups configuration */

266

const DEFAULT_ORDERED_GROUPS: string[];

267

```

268

269

**Usage Examples:**

270

271

```typescript

272

import {

273

LifeCycleObserverOptions,

274

DEFAULT_ORDERED_GROUPS,

275

Application

276

} from "@loopback/core";

277

278

// Application with custom lifecycle options

279

const app = new Application();

280

281

// Configure lifecycle observer options

282

app.bind('lifeCycleObserver.options').to({

283

orderedGroups: ['database', 'cache', 'messaging', 'server'],

284

disabledGroups: ['debug-tools'],

285

parallel: true

286

} as LifeCycleObserverOptions);

287

288

// Use default groups (typically just ['server'])

289

console.log('Default groups:', DEFAULT_ORDERED_GROUPS);

290

291

// Sequential execution for critical services

292

const criticalOptions: LifeCycleObserverOptions = {

293

orderedGroups: ['database', 'auth', 'server'],

294

parallel: false // Execute sequentially within groups

295

};

296

```

297

298

### Lifecycle Observer Groups

299

300

Type definition for organizing lifecycle observers into logical groups with coordinated execution.

301

302

```typescript { .api }

303

/**

304

* A group of life cycle observers

305

*/

306

interface LifeCycleObserverGroup {

307

/** Observer group name */

308

group: string;

309

310

/** Bindings for observers within the group */

311

bindings: Readonly<Binding<LifeCycleObserver>>[];

312

}

313

```

314

315

**Usage Examples:**

316

317

```typescript

318

import { LifeCycleObserverGroup, lifeCycleObserver } from "@loopback/core";

319

320

// Observers in different groups

321

@lifeCycleObserver('database')

322

class DatabaseConnectionObserver implements LifeCycleObserver {

323

async init(): Promise<void> {

324

console.log('Database connection initializing...');

325

}

326

}

327

328

@lifeCycleObserver('database')

329

class DatabaseMigrationObserver implements LifeCycleObserver {

330

async start(): Promise<void> {

331

console.log('Running database migrations...');

332

}

333

}

334

335

@lifeCycleObserver('server')

336

class HttpServerObserver implements LifeCycleObserver {

337

async start(): Promise<void> {

338

console.log('HTTP server starting...');

339

}

340

}

341

342

// Groups will be organized as:

343

// {

344

// group: 'database',

345

// bindings: [DatabaseConnectionObserver, DatabaseMigrationObserver]

346

// }

347

// {

348

// group: 'server',

349

// bindings: [HttpServerObserver]

350

// }

351

```

352

353

### Application Lifecycle Integration

354

355

How lifecycle management integrates with the main Application class.

356

357

**Usage Examples:**

358

359

```typescript

360

import { Application, lifeCycleObserver, LifeCycleObserver } from "@loopback/core";

361

362

@lifeCycleObserver('cache')

363

class RedisObserver implements LifeCycleObserver {

364

async init(): Promise<void> {

365

console.log('Connecting to Redis...');

366

}

367

368

async start(): Promise<void> {

369

console.log('Redis cache ready');

370

}

371

372

async stop(): Promise<void> {

373

console.log('Disconnecting from Redis...');

374

}

375

}

376

377

@lifeCycleObserver('server')

378

class WebServerObserver implements LifeCycleObserver {

379

async start(): Promise<void> {

380

console.log('Web server listening...');

381

}

382

383

async stop(): Promise<void> {

384

console.log('Web server shut down');

385

}

386

}

387

388

const app = new Application();

389

390

// Register lifecycle observers

391

app.lifeCycleObserver(RedisObserver);

392

app.lifeCycleObserver(WebServerObserver);

393

394

// Application coordinates all observers

395

await app.start();

396

// Output:

397

// Connecting to Redis...

398

// Redis cache ready

399

// Web server listening...

400

401

await app.stop();

402

// Output:

403

// Web server shut down

404

// Disconnecting from Redis...

405

```

406

407

## Types

408

409

```typescript { .api }

410

type ValueOrPromise<T> = T | Promise<T>;

411

412

interface LifeCycleObserverGroup {

413

group: string;

414

bindings: Readonly<Binding<LifeCycleObserver>>[];

415

}

416

417

interface LifeCycleObserverOptions {

418

orderedGroups: string[];

419

disabledGroups?: string[];

420

parallel?: boolean;

421

}

422

423

const DEFAULT_ORDERED_GROUPS: string[];

424

```