[SOLVED] I'm pretty new to NestJS and trying to get my head around durable providers but i can't get them to work.
My scenario is that i have a service with some logic and two providers that implement the same interface to get some data. Depending on a custom header value i want to use Provider1 or Provider2 and the service itself does not have to know about the existing provider implementations.
Since i'm in a request scoped scenario but i know there are only 2 possible dependency-subtrees i want to use durable providers that the dependencies are not newly initialised for each request but reused instead.
I set up the ContextIdStrategy as described in the official docs and it is executed on each request but i miss the part how to connect my provider implementations with the ContextSubtreeIds created in the ContextIdStrategy.
Interface:
export abstract class ITest {
  abstract getData(): string;
}
Implementations:
export class Test1Provider implements ITest {
  getData() {
    return "TEST1";
  }
}
export class Test2Provider implements ITest {
  getData() {
    return "TEST2";
  }
}
Service:
@Injectable()
export class AppService {
  constructor(private readonly testProvider: ITest) {}
  getHello(): string {
    return this.testProvider.getData();
  }
}
Controller:
@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}
  @Get()
  getData(): string {
    return this.appService.getData();
  }
}
ContextIdStrategy:
const providers = new Map<string, ContextId>([
  ["provider1", ContextIdFactory.create()],
  ["provider2", ContextIdFactory.create()],
]);
export class AggregateByProviderContextIdStrategy implements ContextIdStrategy {
  attach(contextId: ContextId, request: Request) {
    const providerId = request.headers["x-provider-id"] as string;
    let providerSubTreeId: ContextId;
    if (providerId == "provider1") {
      providerSubTreeId = providers["provider1"];
    } else if (providerId == "provider2") {
      providerSubTreeId = providers["provider2"];
    } else {
      throw Error(`x-provider-id ${providerId} not supported`);
    }
    // If tree is not durable, return the original "contextId" object
    return (info: HostComponentInfo) =>
      info.isTreeDurable ? providerSubTreeId : contextId;
  }
}
Main:
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  ContextIdFactory.apply(new AggregateByProviderContextIdStrategy());
  await app.listen(3000);
}
bootstrap();
Module:
@Module({
  imports: [],
  controllers: [AppController],
  providers: [
    {
      provide: ITest,
      useFactory: () => {
        // THIS IS THE MISSING PIECE. 
        // Return either Test1Provider or Test2Provider based on the ContextSubtreeId 
        // which is created by the ContextIdStrategy
        return new Test1Provider();
      },
    },
    AppService,
  ],
})
export class AppModule {}