or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

account-settings.mdalias-version-management.mdclient-management.mdconcurrency-performance.mdevent-source-mapping.mdfunction-invocation.mdfunction-management.mdfunction-url-management.mdhigh-level-invocation.mdindex.mdlayer-management.mdpermissions-policies.mdruntime-management.mdsecurity-code-signing.mdtagging.mdwaiters-polling.md

waiters-polling.mddocs/

0

# Waiters and Polling

1

2

Automated polling utilities for Lambda resources that wait until functions, versions, and configurations reach desired states, providing robust handling of asynchronous operations with configurable retry policies.

3

4

## Capabilities

5

6

### AWSLambdaWaiters

7

8

Central waiter class providing pre-configured polling strategies for common Lambda resource state transitions.

9

10

```java { .api }

11

/**

12

* Provides waiter objects for polling Lambda resources until desired state

13

* Handles common asynchronous operations with automatic retry and backoff

14

*/

15

public class AWSLambdaWaiters {

16

17

/**

18

* Creates waiters instance for Lambda client

19

* @param client AWSLambda client for resource polling

20

* @return Configured waiters instance

21

*/

22

public static AWSLambdaWaiters of(AWSLambda client);

23

24

/**

25

* Waits until Lambda function exists and is accessible

26

* Polls GetFunction API until function is found or timeout reached

27

* @return Waiter configured for function existence checking

28

* Configuration: 20 attempts, 1 second delay between attempts

29

*/

30

public Waiter<GetFunctionRequest> functionExists();

31

32

/**

33

* Waits until function configuration state is Active

34

* Monitors function state transitions during updates and deployments

35

* @return Waiter configured for function active state

36

* Configuration: 60 attempts, 5 seconds delay between attempts (5 minutes total)

37

*/

38

public Waiter<GetFunctionConfigurationRequest> functionActive();

39

40

/**

41

* Waits until function update operation completes successfully

42

* Monitors LastUpdateStatus until Successful or Failed state reached

43

* @return Waiter configured for function update completion

44

* Configuration: 60 attempts, 5 seconds delay between attempts (5 minutes total)

45

*/

46

public Waiter<GetFunctionConfigurationRequest> functionUpdated();

47

48

/**

49

* Waits until published function version becomes active and ready for invocation

50

* Ensures version is fully deployed and available across all regions

51

* @return Waiter configured for published version active state

52

* Configuration: 312 attempts, 5 seconds delay between attempts (26 minutes total)

53

*/

54

public Waiter<GetFunctionConfigurationRequest> publishedVersionActive();

55

}

56

```

57

58

### Waiter Interface and Configuration

59

60

Core waiter functionality with customizable polling behavior and error handling.

61

62

```java { .api }

63

/**

64

* Generic waiter interface for polling AWS resources until desired state

65

* @param <T> Request type for the polling operation

66

*/

67

public interface Waiter<T> {

68

69

/**

70

* Synchronously waits until resource reaches desired state

71

* Blocks calling thread until condition met or timeout exceeded

72

* @param request Request object for polling operation

73

* @return WaiterResult containing final state and timing information

74

* @throws WaiterTimedOutException if maximum attempts exceeded

75

* @throws WaiterUnrecoverableException if unrecoverable error occurs

76

*/

77

WaiterResult<T> run(T request) throws WaiterTimedOutException, WaiterUnrecoverableException;

78

79

/**

80

* Asynchronously waits until resource reaches desired state

81

* Returns immediately with Future for non-blocking operation

82

* @param request Request object for polling operation

83

* @return Future containing WaiterResult when operation completes

84

*/

85

Future<WaiterResult<T>> runAsync(T request);

86

87

/**

88

* Asynchronously waits with custom callback handling

89

* @param request Request object for polling operation

90

* @param callback Handler for waiter events and completion

91

* @return Future for async operation control

92

*/

93

Future<WaiterResult<T>> runAsync(T request, WaiterHandler<T> callback);

94

}

95

96

/**

97

* Result of waiter operation containing state and metadata

98

* @param <T> Request type that was polled

99

*/

100

public class WaiterResult<T> {

101

102

/**

103

* Gets number of polling attempts made

104

* @return Total attempts executed before completion

105

*/

106

public int getAttemptsExecuted();

107

108

/**

109

* Gets final state of waiter operation

110

* @return WaiterState indicating success, failure, or timeout

111

*/

112

public WaiterState getWaiterState();

113

}

114

115

public enum WaiterState {

116

SUCCESS, // Desired condition met

117

RETRY, // Condition not met, will retry

118

FAILURE // Unrecoverable failure occurred

119

}

120

```

121

122

### Waiter Exception Handling

123

124

Specialized exceptions for different waiter failure scenarios.

125

126

```java { .api }

127

/**

128

* Exception thrown when waiter times out before reaching desired state

129

* Indicates maximum attempts were exceeded without success

130

*/

131

public class WaiterTimedOutException extends Exception {

132

133

/**

134

* Gets waiter result containing attempt information

135

* @return WaiterResult with details about failed attempts

136

*/

137

public WaiterResult<?> getWaiterResult();

138

}

139

140

/**

141

* Exception thrown when waiter encounters unrecoverable error

142

* Indicates polling cannot continue due to permanent failure condition

143

*/

144

public class WaiterUnrecoverableException extends Exception {

145

146

/**

147

* Creates exception with cause and waiter result

148

* @param message Error description

149

* @param cause Underlying exception that caused failure

150

* @param waiterResult Result containing attempt information

151

*/

152

public WaiterUnrecoverableException(String message, Throwable cause, WaiterResult<?> waiterResult);

153

154

/**

155

* Gets waiter result containing attempt information

156

* @return WaiterResult with details about failed attempts

157

*/

158

public WaiterResult<?> getWaiterResult();

159

}

160

```

161

162

### Waiter Event Handling

163

164

Callback interface for monitoring waiter progress and handling events.

165

166

```java { .api }

167

/**

168

* Handler interface for waiter events and state transitions

169

* Enables custom logic during polling operations

170

* @param <T> Request type being polled

171

*/

172

public interface WaiterHandler<T> {

173

174

/**

175

* Called before each polling attempt

176

* @param context Current waiter execution context

177

*/

178

void onWaiterStart(WaiterExecutionContext<T> context);

179

180

/**

181

* Called after each polling attempt

182

* @param context Current waiter execution context

183

*/

184

void onWaiterSuccess(WaiterExecutionContext<T> context);

185

186

/**

187

* Called when waiter operation fails

188

* @param context Current waiter execution context

189

* @param exception Exception that caused failure

190

*/

191

void onWaiterFailure(WaiterExecutionContext<T> context, Throwable exception);

192

}

193

194

/**

195

* Execution context providing waiter state and metadata

196

* @param <T> Request type being polled

197

*/

198

public class WaiterExecutionContext<T> {

199

200

/**

201

* Gets current polling request

202

* @return Request object for this polling attempt

203

*/

204

public T getRequest();

205

206

/**

207

* Gets current attempt number (0-based)

208

* @return Number of attempts completed so far

209

*/

210

public int getAttemptNumber();

211

212

/**

213

* Gets total time elapsed since waiter start

214

* @return Duration in milliseconds

215

*/

216

public long getElapsedTimeMillis();

217

}

218

```

219

220

## Usage Examples

221

222

### Basic Function Existence Waiting

223

224

```java

225

AWSLambda lambdaClient = AWSLambdaClientBuilder.defaultClient();

226

AWSLambdaWaiters waiters = AWSLambdaWaiters.of(lambdaClient);

227

228

// Wait for function to exist after creation

229

GetFunctionRequest request = new GetFunctionRequest()

230

.withFunctionName("newly-created-function");

231

232

try {

233

WaiterResult<GetFunctionRequest> result = waiters.functionExists().run(request);

234

System.out.println("Function exists after " + result.getAttemptsExecuted() + " attempts");

235

} catch (WaiterTimedOutException e) {

236

System.err.println("Function did not appear within expected time");

237

} catch (WaiterUnrecoverableException e) {

238

System.err.println("Unrecoverable error while waiting: " + e.getMessage());

239

}

240

```

241

242

### Waiting for Function Updates

243

244

```java

245

// Update function code

246

UpdateFunctionCodeRequest updateRequest = new UpdateFunctionCodeRequest()

247

.withFunctionName("my-function")

248

.withS3Bucket("deployment-bucket")

249

.withS3Key("my-function-v2.zip");

250

251

lambdaClient.updateFunctionCode(updateRequest);

252

253

// Wait for update to complete

254

GetFunctionConfigurationRequest configRequest = new GetFunctionConfigurationRequest()

255

.withFunctionName("my-function");

256

257

try {

258

WaiterResult<GetFunctionConfigurationRequest> result =

259

waiters.functionUpdated().run(configRequest);

260

261

System.out.println("Function update completed successfully");

262

System.out.println("Attempts: " + result.getAttemptsExecuted());

263

264

} catch (WaiterTimedOutException e) {

265

System.err.println("Function update timed out after " +

266

e.getWaiterResult().getAttemptsExecuted() + " attempts");

267

} catch (WaiterUnrecoverableException e) {

268

System.err.println("Function update failed: " + e.getMessage());

269

}

270

```

271

272

### Asynchronous Waiting with Callbacks

273

274

```java

275

// Implement custom waiter handler

276

WaiterHandler<GetFunctionConfigurationRequest> handler = new WaiterHandler<GetFunctionConfigurationRequest>() {

277

278

@Override

279

public void onWaiterStart(WaiterExecutionContext<GetFunctionConfigurationRequest> context) {

280

System.out.println("Starting wait attempt " + (context.getAttemptNumber() + 1));

281

}

282

283

@Override

284

public void onWaiterSuccess(WaiterExecutionContext<GetFunctionConfigurationRequest> context) {

285

System.out.println("Function is now active after " +

286

context.getElapsedTimeMillis() + "ms");

287

}

288

289

@Override

290

public void onWaiterFailure(WaiterExecutionContext<GetFunctionConfigurationRequest> context,

291

Throwable exception) {

292

System.err.println("Wait failed at attempt " + context.getAttemptNumber() +

293

": " + exception.getMessage());

294

}

295

};

296

297

// Wait asynchronously for function to become active

298

GetFunctionConfigurationRequest configRequest = new GetFunctionConfigurationRequest()

299

.withFunctionName("deployment-target");

300

301

Future<WaiterResult<GetFunctionConfigurationRequest>> future =

302

waiters.functionActive().runAsync(configRequest, handler);

303

304

// Continue with other work while waiting

305

performOtherOperations();

306

307

// Get result when needed

308

try {

309

WaiterResult<GetFunctionConfigurationRequest> result = future.get(10, TimeUnit.MINUTES);

310

System.out.println("Function is active and ready for use");

311

} catch (TimeoutException e) {

312

System.err.println("Async wait timed out");

313

future.cancel(true);

314

}

315

```

316

317

### Version Publication Workflow

318

319

```java

320

public class VersionDeploymentManager {

321

private final AWSLambda lambdaClient;

322

private final AWSLambdaWaiters waiters;

323

324

public VersionDeploymentManager(AWSLambda lambdaClient) {

325

this.lambdaClient = lambdaClient;

326

this.waiters = AWSLambdaWaiters.of(lambdaClient);

327

}

328

329

/**

330

* Deploy new version and wait for it to be fully active

331

*/

332

public String deployNewVersion(String functionName, String description) {

333

try {

334

// Publish new version

335

PublishVersionRequest publishRequest = new PublishVersionRequest()

336

.withFunctionName(functionName)

337

.withDescription(description);

338

339

PublishVersionResult publishResult = lambdaClient.publishVersion(publishRequest);

340

String newVersion = publishResult.getVersion();

341

342

System.out.println("Published version " + newVersion + ", waiting for activation...");

343

344

// Wait for version to become active

345

GetFunctionConfigurationRequest configRequest = new GetFunctionConfigurationRequest()

346

.withFunctionName(functionName)

347

.withQualifier(newVersion);

348

349

WaiterResult<GetFunctionConfigurationRequest> waiterResult =

350

waiters.publishedVersionActive().run(configRequest);

351

352

System.out.println("Version " + newVersion + " is now active after " +

353

waiterResult.getAttemptsExecuted() + " polling attempts");

354

355

return newVersion;

356

357

} catch (WaiterTimedOutException e) {

358

throw new RuntimeException("Version activation timed out after " +

359

e.getWaiterResult().getAttemptsExecuted() + " attempts");

360

} catch (WaiterUnrecoverableException e) {

361

throw new RuntimeException("Version activation failed permanently", e);

362

}

363

}

364

365

/**

366

* Deploy with alias update and traffic shifting

367

*/

368

public void deployToAlias(String functionName, String aliasName, String description) {

369

try {

370

// Deploy new version

371

String newVersion = deployNewVersion(functionName, description);

372

373

// Update alias to point to new version

374

UpdateAliasRequest aliasRequest = new UpdateAliasRequest()

375

.withFunctionName(functionName)

376

.withName(aliasName)

377

.withFunctionVersion(newVersion);

378

379

lambdaClient.updateAlias(aliasRequest);

380

System.out.println("Alias " + aliasName + " updated to version " + newVersion);

381

382

} catch (Exception e) {

383

System.err.println("Deployment failed: " + e.getMessage());

384

throw e;

385

}

386

}

387

}

388

```

389

390

### Batch Operations with Waiters

391

392

```java

393

public class BatchFunctionManager {

394

private final AWSLambda lambdaClient;

395

private final AWSLambdaWaiters waiters;

396

private final ExecutorService executorService;

397

398

public BatchFunctionManager(AWSLambda lambdaClient) {

399

this.lambdaClient = lambdaClient;

400

this.waiters = AWSLambdaWaiters.of(lambdaClient);

401

this.executorService = Executors.newFixedThreadPool(10);

402

}

403

404

/**

405

* Update multiple functions concurrently and wait for all to complete

406

*/

407

public void updateFunctionsConcurrently(List<String> functionNames,

408

Map<String, FunctionCode> codeUpdates) {

409

List<Future<String>> futures = new ArrayList<>();

410

411

// Start all updates concurrently

412

for (String functionName : functionNames) {

413

Future<String> future = executorService.submit(() -> {

414

return updateSingleFunction(functionName, codeUpdates.get(functionName));

415

});

416

futures.add(future);

417

}

418

419

// Wait for all updates to complete

420

List<String> results = new ArrayList<>();

421

for (Future<String> future : futures) {

422

try {

423

String result = future.get(10, TimeUnit.MINUTES);

424

results.add(result);

425

} catch (Exception e) {

426

System.err.println("Function update failed: " + e.getMessage());

427

}

428

}

429

430

System.out.println("Updated " + results.size() + " functions successfully");

431

}

432

433

private String updateSingleFunction(String functionName, FunctionCode code) {

434

try {

435

// Update function code

436

UpdateFunctionCodeRequest updateRequest = new UpdateFunctionCodeRequest()

437

.withFunctionName(functionName)

438

.withS3Bucket(code.getS3Bucket())

439

.withS3Key(code.getS3Key());

440

441

lambdaClient.updateFunctionCode(updateRequest);

442

443

// Wait for update completion

444

GetFunctionConfigurationRequest configRequest = new GetFunctionConfigurationRequest()

445

.withFunctionName(functionName);

446

447

WaiterResult<GetFunctionConfigurationRequest> result =

448

waiters.functionUpdated().run(configRequest);

449

450

return "Function " + functionName + " updated in " +

451

result.getAttemptsExecuted() + " attempts";

452

453

} catch (Exception e) {

454

throw new RuntimeException("Failed to update function " + functionName, e);

455

}

456

}

457

}

458

```

459

460

### Custom Waiter Implementation

461

462

```java

463

public class CustomLambdaWaiter {

464

private final AWSLambda lambdaClient;

465

466

public CustomLambdaWaiter(AWSLambda lambdaClient) {

467

this.lambdaClient = lambdaClient;

468

}

469

470

/**

471

* Wait for provisioned concurrency to be ready with custom polling

472

*/

473

public void waitForProvisionedConcurrency(String functionName, String qualifier,

474

int maxAttempts, long delayMs) {

475

476

GetProvisionedConcurrencyConfigRequest request = new GetProvisionedConcurrencyConfigRequest()

477

.withFunctionName(functionName)

478

.withQualifier(qualifier);

479

480

int attempt = 0;

481

while (attempt < maxAttempts) {

482

try {

483

GetProvisionedConcurrencyConfigResult result =

484

lambdaClient.getProvisionedConcurrencyConfig(request);

485

486

ProvisionedConcurrencyStatus status = result.getStatus();

487

System.out.println("Attempt " + (attempt + 1) + ": Status is " + status);

488

489

if (ProvisionedConcurrencyStatus.READY.equals(status)) {

490

System.out.println("Provisioned concurrency is ready!");

491

return;

492

} else if (ProvisionedConcurrencyStatus.FAILED.equals(status)) {

493

throw new RuntimeException("Provisioned concurrency failed: " +

494

result.getStatusReason());

495

}

496

497

// Wait before next attempt

498

Thread.sleep(delayMs);

499

attempt++;

500

501

} catch (InterruptedException e) {

502

Thread.currentThread().interrupt();

503

throw new RuntimeException("Interrupted while waiting", e);

504

}

505

}

506

507

throw new RuntimeException("Provisioned concurrency did not become ready after " +

508

maxAttempts + " attempts");

509

}

510

511

/**

512

* Wait for multiple functions to be active with progress reporting

513

*/

514

public void waitForMultipleFunctions(List<String> functionNames) {

515

Set<String> pendingFunctions = new HashSet<>(functionNames);

516

int totalAttempts = 0;

517

final int maxAttempts = 60;

518

519

while (!pendingFunctions.isEmpty() && totalAttempts < maxAttempts) {

520

Iterator<String> iterator = pendingFunctions.iterator();

521

522

while (iterator.hasNext()) {

523

String functionName = iterator.next();

524

525

try {

526

GetFunctionConfigurationRequest request = new GetFunctionConfigurationRequest()

527

.withFunctionName(functionName);

528

529

GetFunctionConfigurationResult result =

530

lambdaClient.getFunctionConfiguration(request);

531

532

if (State.Active.equals(result.getState()) &&

533

LastUpdateStatus.Successful.equals(result.getLastUpdateStatus())) {

534

535

System.out.println("Function " + functionName + " is now active");

536

iterator.remove();

537

}

538

539

} catch (ResourceNotFoundException e) {

540

// Function doesn't exist yet, keep waiting

541

}

542

}

543

544

if (!pendingFunctions.isEmpty()) {

545

System.out.println("Still waiting for " + pendingFunctions.size() +

546

" functions: " + pendingFunctions);

547

548

try {

549

Thread.sleep(5000);

550

} catch (InterruptedException e) {

551

Thread.currentThread().interrupt();

552

throw new RuntimeException("Interrupted while waiting", e);

553

}

554

}

555

556

totalAttempts++;

557

}

558

559

if (!pendingFunctions.isEmpty()) {

560

throw new RuntimeException("Functions not ready after maximum attempts: " +

561

pendingFunctions);

562

}

563

564

System.out.println("All functions are now active and ready");

565

}

566

}

567

```

568

569

## Exception Handling

570

571

Common exceptions when using waiters:

572

573

- **WaiterTimedOutException**: Maximum polling attempts exceeded without reaching desired state

574

- **WaiterUnrecoverableException**: Permanent failure condition prevents continued polling

575

- **ResourceNotFoundException**: Target resource does not exist and cannot be polled

576

- **InterruptedException**: Waiter thread was interrupted during polling delay

577

- **ExecutionException**: Async waiter operation failed with underlying exception

578

579

## Best Practices

580

581

### Waiter Configuration

582

- Choose appropriate timeout values based on expected operation duration

583

- Use shorter delays for fast operations, longer delays for deployment operations

584

- Consider resource limits and API throttling when setting polling frequency

585

- Implement exponential backoff for operations prone to transient failures

586

587

### Error Handling

588

- Distinguish between temporary failures (retry) and permanent failures (abort)

589

- Log waiter progress for debugging and monitoring purposes

590

- Implement fallback strategies for waiter timeouts

591

- Use circuit breaker patterns to prevent cascading failures

592

593

### Performance Optimization

594

- Use asynchronous waiters for non-blocking operations

595

- Batch multiple waiter operations when possible

596

- Monitor API usage to avoid throttling limits

597

- Cache waiter instances to reduce initialization overhead

598

599

### Monitoring and Observability

600

- Track waiter success rates and average completion times

601

- Set up alerts for frequent waiter timeouts or failures

602

- Log waiter events for troubleshooting deployment issues

603

- Use structured logging for correlation with other operations