or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-objects.mdbucket-operations.mdclient-setup.mdindex.mdnotifications.mdobject-operations.mdpresigned-operations.mdtypes-and-errors.md

notifications.mddocs/

0

# Notifications

1

2

This document covers the MinIO notification system, including bucket notification configuration, event types, polling mechanisms, and notification target setup for real-time event processing.

3

4

## Notification Overview

5

6

MinIO supports bucket notifications that trigger when specific events occur on objects. Notifications can be sent to various targets like SNS topics, SQS queues, or Lambda functions, and can also be consumed via polling.

7

8

## Event Types

9

10

### Standard S3 Events

11

12

```javascript { .api }

13

// Import event type constants

14

import {

15

ObjectCreatedAll,

16

ObjectCreatedPut,

17

ObjectCreatedPost,

18

ObjectCreatedCopy,

19

ObjectCreatedCompleteMultipartUpload,

20

ObjectRemovedAll,

21

ObjectRemovedDelete,

22

ObjectRemovedDeleteMarkerCreated,

23

ObjectReducedRedundancyLostObject

24

} from 'minio'

25

26

// Event type values

27

ObjectCreatedAll = 's3:ObjectCreated:*'

28

ObjectCreatedPut = 's3:ObjectCreated:Put'

29

ObjectCreatedPost = 's3:ObjectCreated:Post'

30

ObjectCreatedCopy = 's3:ObjectCreated:Copy'

31

ObjectCreatedCompleteMultipartUpload = 's3:ObjectCreated:CompleteMultipartUpload'

32

ObjectRemovedAll = 's3:ObjectRemoved:*'

33

ObjectRemovedDelete = 's3:ObjectRemoved:Delete'

34

ObjectRemovedDeleteMarkerCreated = 's3:ObjectRemoved:DeleteMarkerCreated'

35

ObjectReducedRedundancyLostObject = 's3:ReducedRedundancyLostObject'

36

```

37

38

#### Event Type Usage

39

40

```javascript { .api }

41

// Listen for all object creation events

42

const events = [ObjectCreatedAll]

43

44

// Listen for specific events

45

const specificEvents = [

46

ObjectCreatedPut,

47

ObjectCreatedPost,

48

ObjectRemovedDelete

49

]

50

51

// Listen for all events (creation and deletion)

52

const allEvents = [ObjectCreatedAll, ObjectRemovedAll]

53

```

54

55

## Notification Configuration

56

57

### NotificationConfig Class

58

59

```typescript { .api }

60

import { NotificationConfig } from 'minio'

61

62

class NotificationConfig {

63

// Methods

64

add(target: TargetConfig): void // Add notification target

65

}

66

```

67

68

### Base TargetConfig Class

69

70

```typescript { .api }

71

abstract class TargetConfig {

72

// Methods

73

setId(id: unknown): void // Set target identifier

74

addEvent(newevent: Event): void // Add event type to listen for

75

addFilterSuffix(suffix: string): void // Add object suffix filter

76

addFilterPrefix(prefix: string): void // Add object prefix filter

77

}

78

```

79

80

### Target Types

81

82

#### TopicConfig (SNS)

83

84

```typescript { .api }

85

import { TopicConfig } from 'minio'

86

87

class TopicConfig extends TargetConfig {

88

constructor(arn: string) // SNS topic ARN

89

}

90

```

91

92

#### QueueConfig (SQS)

93

94

```typescript { .api }

95

import { QueueConfig } from 'minio'

96

97

class QueueConfig extends TargetConfig {

98

constructor(arn: string) // SQS queue ARN

99

}

100

```

101

102

#### CloudFunctionConfig (Lambda)

103

104

```typescript { .api }

105

import { CloudFunctionConfig } from 'minio'

106

107

class CloudFunctionConfig extends TargetConfig {

108

constructor(arn: string) // Lambda function ARN

109

}

110

```

111

112

### Set Bucket Notification

113

114

```javascript { .api }

115

client.setBucketNotification(bucketName, config, callback)

116

117

// Parameters

118

bucketName: string // Bucket name

119

config: object // Notification configuration object

120

callback: function // Callback function (err) => void

121

122

// Note: This method uses callback pattern only

123

```

124

125

### Get Bucket Notification

126

127

```javascript { .api }

128

client.getBucketNotification(bucketName, callback)

129

130

// Parameters

131

bucketName: string // Bucket name

132

callback: function // Callback function (err, config) => void

133

```

134

135

### Remove All Notifications

136

137

```javascript { .api }

138

client.removeAllBucketNotification(bucketName, callback)

139

140

// Parameters

141

bucketName: string // Bucket name

142

callback: function // Callback function (err) => void

143

```

144

145

### Notification Configuration Examples

146

147

```javascript { .api }

148

import {

149

NotificationConfig,

150

TopicConfig,

151

QueueConfig,

152

CloudFunctionConfig,

153

ObjectCreatedAll,

154

ObjectRemovedAll

155

} from 'minio'

156

157

// Configure SNS topic notification

158

const topicConfig = new TopicConfig('arn:aws:sns:us-east-1:123456789012:my-topic')

159

topicConfig.addEvent(ObjectCreatedAll)

160

topicConfig.addFilterPrefix('photos/')

161

topicConfig.addFilterSuffix('.jpg')

162

163

const notificationConfig = new NotificationConfig()

164

notificationConfig.add(topicConfig)

165

166

// Set bucket notification

167

client.setBucketNotification('my-bucket', notificationConfig, (err) => {

168

if (err) throw err

169

console.log('Notification configured successfully')

170

})

171

172

// Configure multiple notification targets

173

const snsConfig = new TopicConfig('arn:aws:sns:us-east-1:123456789012:uploads-topic')

174

snsConfig.addEvent(ObjectCreatedPut)

175

snsConfig.addEvent(ObjectCreatedPost)

176

snsConfig.addFilterPrefix('uploads/')

177

178

const sqsConfig = new QueueConfig('arn:aws:sqs:us-east-1:123456789012:deletions-queue')

179

sqsConfig.addEvent(ObjectRemovedDelete)

180

181

const lambdaConfig = new CloudFunctionConfig('arn:aws:lambda:us-east-1:123456789012:function:processImage')

182

lambdaConfig.addEvent(ObjectCreatedAll)

183

lambdaConfig.addFilterSuffix('.jpg')

184

lambdaConfig.addFilterSuffix('.png')

185

186

const multiTargetConfig = new NotificationConfig()

187

multiTargetConfig.add(snsConfig)

188

multiTargetConfig.add(sqsConfig)

189

multiTargetConfig.add(lambdaConfig)

190

191

client.setBucketNotification('multi-notifications', multiTargetConfig, (err) => {

192

if (err) throw err

193

console.log('Multiple notifications configured')

194

})

195

196

// Get current notification configuration

197

client.getBucketNotification('my-bucket', (err, config) => {

198

if (err) throw err

199

console.log('Current notification config:', JSON.stringify(config, null, 2))

200

})

201

202

// Remove all notifications

203

client.removeAllBucketNotification('my-bucket', (err) => {

204

if (err) throw err

205

console.log('All notifications removed')

206

})

207

```

208

209

## Notification Polling

210

211

### NotificationPoller Class

212

213

```typescript { .api }

214

import { NotificationPoller } from 'minio'

215

216

class NotificationPoller extends EventEmitter {

217

constructor(

218

client: TypedClient, // MinIO client instance

219

bucketName: string, // Bucket to monitor

220

prefix: string, // Object prefix filter

221

suffix: string, // Object suffix filter

222

events: NotificationEvent[] // Events to listen for

223

)

224

225

// Methods

226

start(): void // Start polling for notifications

227

stop(): void // Stop polling for notifications

228

229

// Events (extends EventEmitter)

230

on('notification', listener: (notification) => void): this

231

on('error', listener: (error) => void): this

232

}

233

```

234

235

### Listen for Notifications

236

237

```javascript { .api }

238

const notificationStream = client.listenBucketNotification(bucketName, prefix, suffix, events)

239

240

// Parameters

241

bucketName: string // Bucket name

242

prefix: string // Object prefix filter (empty string for all)

243

suffix: string // Object suffix filter (empty string for all)

244

events: string[] // Array of event types to listen for

245

246

// Returns: EventEmitter

247

```

248

249

### Polling Examples

250

251

```javascript { .api }

252

// Listen for all object creation events

253

const notificationStream = client.listenBucketNotification(

254

'my-bucket',

255

'', // No prefix filter (all objects)

256

'', // No suffix filter (all objects)

257

[ObjectCreatedAll]

258

)

259

260

notificationStream.on('notification', (record) => {

261

console.log('New object created:', record.s3.object.key)

262

console.log('Event name:', record.eventName)

263

console.log('Bucket:', record.s3.bucket.name)

264

console.log('Object size:', record.s3.object.size)

265

})

266

267

notificationStream.on('error', (err) => {

268

console.error('Notification error:', err)

269

})

270

271

// Listen for photo uploads only

272

const photoNotifications = client.listenBucketNotification(

273

'photos',

274

'uploads/', // Only objects with 'uploads/' prefix

275

'.jpg', // Only .jpg files

276

[ObjectCreatedPut, ObjectCreatedPost]

277

)

278

279

photoNotifications.on('notification', (record) => {

280

const objectKey = record.s3.object.key

281

const bucketName = record.s3.bucket.name

282

283

console.log(`New photo uploaded: ${objectKey}`)

284

285

// Process the uploaded photo

286

processNewPhoto(bucketName, objectKey)

287

})

288

289

// Listen for deletion events

290

const deletionNotifications = client.listenBucketNotification(

291

'documents',

292

'important/', // Monitor important documents

293

'', // All file types

294

[ObjectRemovedDelete, ObjectRemovedDeleteMarkerCreated]

295

)

296

297

deletionNotifications.on('notification', (record) => {

298

console.log('Document deleted:', record.s3.object.key)

299

300

// Log deletion for audit

301

auditLog.record({

302

event: 'document_deleted',

303

object: record.s3.object.key,

304

timestamp: record.eventTime,

305

source: record.eventSource

306

})

307

})

308

309

// Advanced notification handling with filtering

310

async function processNewPhoto(bucketName, objectKey) {

311

try {

312

// Get object metadata

313

const stat = await client.statObject(bucketName, objectKey)

314

315

// Process only if file is reasonable size

316

if (stat.size > 10 * 1024 * 1024) { // > 10MB

317

console.log('Photo too large, skipping processing')

318

return

319

}

320

321

// Download and process photo

322

const photoStream = await client.getObject(bucketName, objectKey)

323

// ... image processing logic

324

325

} catch (error) {

326

console.error('Failed to process photo:', error)

327

}

328

}

329

```

330

331

### Advanced Polling Patterns

332

333

```javascript { .api }

334

// Multiple concurrent listeners

335

function setupMultipleListeners(bucketName) {

336

// Listen for uploads

337

const uploadListener = client.listenBucketNotification(

338

bucketName, '', '', [ObjectCreatedAll]

339

)

340

341

// Listen for deletions

342

const deleteListener = client.listenBucketNotification(

343

bucketName, '', '', [ObjectRemovedAll]

344

)

345

346

// Separate handlers for different event types

347

uploadListener.on('notification', handleUpload)

348

deleteListener.on('notification', handleDeletion)

349

350

// Common error handling

351

[uploadListener, deleteListener].forEach(listener => {

352

listener.on('error', (err) => {

353

console.error('Notification listener error:', err)

354

355

// Implement retry logic

356

setTimeout(() => {

357

console.log('Restarting notification listener...')

358

// Restart listeners if needed

359

}, 5000)

360

})

361

})

362

363

return { uploadListener, deleteListener }

364

}

365

366

function handleUpload(record) {

367

const { eventName, s3: { bucket, object } } = record

368

369

console.log(`Upload event: ${eventName}`)

370

console.log(`Bucket: ${bucket.name}, Object: ${object.key}`)

371

372

// Route to appropriate handler based on object type

373

if (object.key.endsWith('.jpg') || object.key.endsWith('.png')) {

374

processImage(bucket.name, object.key)

375

} else if (object.key.endsWith('.pdf')) {

376

processDocument(bucket.name, object.key)

377

} else if (object.key.endsWith('.csv')) {

378

processData(bucket.name, object.key)

379

}

380

}

381

382

function handleDeletion(record) {

383

const { eventName, s3: { bucket, object } } = record

384

385

console.log(`Deletion event: ${eventName}`)

386

387

// Clean up related resources

388

cleanupRelatedData(bucket.name, object.key)

389

390

// Update search index

391

updateSearchIndex('remove', bucket.name, object.key)

392

}

393

394

// Graceful shutdown

395

process.on('SIGINT', () => {

396

console.log('Shutting down notification listeners...')

397

398

// Stop all listeners

399

Object.values(listeners).forEach(listener => {

400

if (listener && listener.stop) {

401

listener.stop()

402

}

403

})

404

405

process.exit(0)

406

})

407

```

408

409

## ARN Building Utility

410

411

```javascript { .api }

412

import { buildARN } from 'minio'

413

414

const arn = buildARN(partition, service, region, accountId, resource)

415

416

// Parameters

417

partition: string // AWS partition ('aws', 'aws-cn', 'aws-us-gov')

418

service: string // AWS service ('sns', 'sqs', 'lambda')

419

region: string // AWS region ('us-east-1', 'eu-west-1', etc.)

420

accountId: string // AWS account ID

421

resource: string // Resource identifier

422

423

// Returns: string - Complete ARN

424

```

425

426

### ARN Examples

427

428

```javascript { .api }

429

// Build SNS topic ARN

430

const snsArn = buildARN('aws', 'sns', 'us-east-1', '123456789012', 'my-topic')

431

console.log(snsArn) // arn:aws:sns:us-east-1:123456789012:my-topic

432

433

// Build SQS queue ARN

434

const sqsArn = buildARN('aws', 'sqs', 'us-west-2', '123456789012', 'my-queue')

435

console.log(sqsArn) // arn:aws:sqs:us-west-2:123456789012:my-queue

436

437

// Build Lambda function ARN

438

const lambdaArn = buildARN('aws', 'lambda', 'eu-west-1', '123456789012', 'function:myFunction')

439

console.log(lambdaArn) // arn:aws:lambda:eu-west-1:123456789012:function:myFunction

440

441

// Use built ARNs in notification config

442

const config = new NotificationConfig()

443

444

const topic = new TopicConfig(buildARN('aws', 'sns', 'us-east-1', '123456789012', 'uploads'))

445

topic.addEvent(ObjectCreatedAll)

446

447

const queue = new QueueConfig(buildARN('aws', 'sqs', 'us-east-1', '123456789012', 'processing'))

448

queue.addEvent(ObjectCreatedPut)

449

450

config.add(topic)

451

config.add(queue)

452

```

453

454

## Notification Record Format

455

456

When notifications are received, they follow the S3 notification record format:

457

458

```javascript { .api }

459

// Example notification record structure

460

const notificationRecord = {

461

eventVersion: '2.1',

462

eventSource: 'minio:s3',

463

eventTime: '2023-01-01T12:00:00.000Z',

464

eventName: 's3:ObjectCreated:Put',

465

userIdentity: {

466

principalId: 'minio'

467

},

468

requestParameters: {

469

principalId: 'minio',

470

region: 'us-east-1',

471

sourceIPAddress: '192.168.1.100'

472

},

473

responseElements: {

474

'x-amz-request-id': '17C5B45A35D8CB22',

475

'x-minio-deployment-id': '9b777c1a-3b3d-4f3c-b1c3-8f5b3a1e9c2d'

476

},

477

s3: {

478

s3SchemaVersion: '1.0',

479

configurationId: 'Config',

480

bucket: {

481

name: 'my-bucket',

482

ownerIdentity: {

483

principalId: 'minio'

484

},

485

arn: 'arn:aws:s3:::my-bucket'

486

},

487

object: {

488

key: 'photos/vacation.jpg',

489

size: 2048576,

490

eTag: 'd41d8cd98f00b204e9800998ecf8427e',

491

contentType: 'image/jpeg',

492

userMetadata: {

493

'x-amz-meta-uploader': 'mobile-app'

494

},

495

sequencer: '17C5B45A35D8CB23'

496

}

497

}

498

}

499

```

500

501

## Error Handling

502

503

```javascript { .api }

504

import { S3Error } from 'minio'

505

506

// Handle notification configuration errors

507

client.setBucketNotification('my-bucket', config, (err) => {

508

if (err) {

509

if (err instanceof S3Error) {

510

switch (err.code) {

511

case 'InvalidArgument':

512

console.error('Invalid notification configuration:', err.message)

513

break

514

case 'UnsupportedNotification':

515

console.error('Notification type not supported:', err.message)

516

break

517

default:

518

console.error('S3 notification error:', err.code, err.message)

519

}

520

} else {

521

console.error('Notification error:', err.message)

522

}

523

}

524

})

525

526

// Handle polling errors

527

const listener = client.listenBucketNotification('bucket', '', '', [ObjectCreatedAll])

528

529

listener.on('error', (err) => {

530

console.error('Notification polling error:', err)

531

532

// Implement exponential backoff retry

533

const retryDelay = Math.min(1000 * Math.pow(2, retryCount), 30000)

534

535

setTimeout(() => {

536

console.log('Retrying notification listener...')

537

// Restart listener

538

}, retryDelay)

539

})

540

```

541

542

## Best Practices

543

544

### 1. Event Filtering

545

- Use prefix and suffix filters to reduce notification volume

546

- Filter events at the source rather than in handlers

547

- Consider object naming strategies that support filtering

548

- Monitor notification volume and costs

549

550

### 2. Reliability

551

- Implement error handling and retry logic

552

- Use dead letter queues for failed notifications

553

- Monitor notification delivery rates

554

- Set appropriate timeouts for processing

555

556

### 3. Performance

557

- Process notifications asynchronously

558

- Use appropriate batching for high-volume events

559

- Consider fan-out patterns for multiple consumers

560

- Monitor processing latency and throughput

561

562

### 4. Security

563

- Use IAM policies to restrict notification access

564

- Validate notification sources

565

- Encrypt sensitive notification data

566

- Audit notification configuration changes

567

568

### 5. Monitoring

569

- Track notification delivery and processing metrics

570

- Set up alerts for notification failures

571

- Monitor resource usage of notification handlers

572

- Log notification events for troubleshooting

573

574

---

575

576

**Next:** [Types and Errors](./types-and-errors.md) - Complete reference for all error classes, types, and interfaces