Skip to content

feat(core): defer initialization connected microservice #15203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 29, 2025

Conversation

isaryy
Copy link
Contributor

@isaryy isaryy commented May 28, 2025

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

Currently, when using app.connectMicroservice(), the microservice is immediately initialized inside the method call. This creates several limitations:

  1. Limited configuration options: Microservice settings can only be applied through inheritAppConfig option and must be set before calling .connectMicroservice()
  2. No post-connection configuration: Adding global handlers, pipes, filters, interceptors, etc. to the returned INestMicroservice object is ineffective because initialization has already completed
  3. Confusing developer experience: The API suggests that you can configure the microservice after connection, but this doesn't work as expected

Example of current limitation:

const app = await NestFactory.create(AppModule);

// This works - configuration before connection
app.useGlobalPipes(new ValidationPipe());

const microservice = app.connectMicroservice(options, { 
  inheritAppConfig: true 
});

// This DOESN'T work - microservice is already initialized
microservice.useGlobalFilters(new ExceptionFilter()); // ❌ Has no effect

Issue Number: N/A

What is the new behavior?

Added a new deferInitialization option to NestHybridApplicationOptions that allows delaying microservice initialization until .listen() is called.

New API:

const app = await NestFactory.create(AppModule);

const microservice = app.connectMicroservice(options, { 
  deferInitialization: true 
});

// Now you can configure the microservice before it's initialized
microservice.useGlobalPipes(new ValidationPipe());
microservice.useGlobalFilters(new GlobalExceptionFilter());
microservice.useGlobalInterceptors(new LoggingInterceptor());
microservice.useGlobalGuards(new AuthGuard());

// Initialization happens here
await microservice.listen() || await app.startAllMicroservices();

Benefits:

  • ✅ Allows post-connection configuration of global handlers
  • ✅ Provides more flexibility in microservice setup
  • ✅ Maintains backward compatibility (default behavior unchanged)
  • ✅ Enables better separation of concerns between connection and configuration
  • ✅ More intuitive developer experience

Implementation Details

Interface Changes

Added deferInitialization property to NestHybridApplicationOptions:

export interface NestHybridApplicationOptions {
  inheritAppConfig?: boolean;
  deferInitialization?: boolean; // New option
}

Code Changes

Modified connectMicroservice method in NestApplication:

public connectMicroservice<T extends object>(
  microserviceOptions: T,
  hybridAppOptions: NestHybridApplicationOptions = {},
): INestMicroservice {
  // ... existing code ...
  
  if (!hybridAppOptions.deferInitialization) {
    instance.registerListeners();
    instance.setIsInitialized(true);
    instance.setIsInitHookCalled(true);
  }
  
  // ... existing code ...
}

Does this PR introduce a breaking change?

  • Yes
  • No

The change is fully backward compatible. When deferInitialization is not specified or set to false, the behavior remains exactly the same as before.

Testing

Added comprehensive tests covering:

  1. Default behavior preservation - ensures existing functionality works unchanged
  2. Deferred initialization - verifies that microservice is not initialized when deferInitialization: true
  3. Manual initialization - confirms that deferred microservices can be properly initialized later

Other information

Migration

No migration is required. Existing code continues to work without changes. To use the new feature, simply add deferInitialization: true to the options:

// Before (still works)
const microservice = app.connectMicroservice(options);

// New feature
const microservice = app.connectMicroservice(options, { 
  deferInitialization: true 
});

@coveralls
Copy link

Pull Request Test Coverage Report for Build c1e68828-0cf7-4679-b5b7-3c91f82e3b76

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 88.94%

Totals Coverage Status
Change from base Build cbdbfe31-770d-4936-b123-f113ab433f9c: 0.0%
Covered Lines: 7197
Relevant Lines: 8092

💛 - Coveralls

@kamilmysliwiec kamilmysliwiec merged commit 521544c into nestjs:master May 29, 2025
2 of 3 checks passed
@kamilmysliwiec
Copy link
Member

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants