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

Proposal: ability to create ChildKernels #199

Closed
lazyoft opened this Issue May 12, 2016 · 3 comments

Comments

Projects
None yet
2 participants
@lazyoft

lazyoft commented May 12, 2016

Context

On our project we provide a way for end users to create their own modules (or plugins) that can interact with our services. In order to do this every module in our framework will need to provide an IKernelModule. This works fine because users can add or change dependencies for ancillary services, but it is also risky, because they could also unbind all of our infrastructure.

To give an example, our module registration is defined as follows:

register(module: IModule) {
    this.kernel.load(module.modules);
    //... other irrelevant stuff here...
}

With this approach we are basically forced to trust the end user not to perform a kernel.unbindAll() on their registration, or for what is worth any kernel.unbind() operation that might disrupt our infrastructure.

Proposal

Create a ChildKernel class, that can accept an IKernel as its parent. Resolution on the ChildKernel should proceed as follows:

  • If the object requested is defined by the ChildKernel, provide such object to the requester
  • If the object is not defined by the ChildKernel, forward the resolution to the ParentKernel
  • In the case of singleton objects the ownership will be of the kernel that has the root definition
  • It should not be possible to allow dependencies from the ParentKernel to the ChildKernel, meaning that an object defined on the ParentKernel cannot access dependencies from the ChildKernel. The other way around is clearly possible.

If this proposal is applied it could allow us and other frameworks that can be module/plugin based to provide a way to register new dependencies without removing cross dependencies, and at the same time it could allow isolation among different modules. To provide an example:

public class ModuleA implements IModule {
     modules: IKernelModule = (kernel: IKernel) => {
        kernel.bind<IMyService>("IMyService").to(ModuleAService);
    }  
}

public class ModuleB implements IModule {
     modules: IKernelModule = (kernel: IKernel) => {
        kernel.bind<IMyService>("IMyService").to(ModuleBService);
    }  
}

In this case both ModuleA and ModuleB define an IMyService implementation, which is needed by their specific modules. Using a common kernel in this case is not feasible, because resolution of the component will result in an error. Neither is having specific conditions or named bindings, because it will expose to the end user part of the module design. With ChildKernels every module can be passed its own ChildKernel and can work in isolation with respect to the other, while at the same time being able to use all the facilities and services provided by the parent kernel.

Ideally we should be able to do something like the following (clearly not the real production code, but it is just to get the idea):

let masterKernel = new Kernel();
// a bunch of masterKernel.bind stuff here...
let moduleAKernel = new ChildKernel(masterKernel);
let moduleBKernel = new ChildKernel(masterKernel);

let moduleA = new ModuleA();
let moduleB = new ModuleB();

moduleAKernel.load(moduleA.modules);
moduleBKernel.load(moduleB.modules);

I'm not sure if this can be done by simply passing an IKernel to the ChildKernel class, because it might not expose some required information or infrastructure for the planning and resolution phases, though.

@remojansen remojansen added this to the 2.1.0-beta.1 milestone May 12, 2016

@remojansen

This comment has been minimized.

Show comment
Hide comment
@remojansen

remojansen May 12, 2016

Member

Hi @lazyoft thanks for this proposal I will work on this as soon. I will release 2.0.0 and then I will work on 2.1.0 which will include this feature.

Member

remojansen commented May 12, 2016

Hi @lazyoft thanks for this proposal I will work on this as soon. I will release 2.0.0 and then I will work on 2.1.0 which will include this feature.

@lazyoft

This comment has been minimized.

Show comment
Hide comment
@lazyoft

lazyoft May 13, 2016

Hi @remojansen thanks for the reply. Looking forward to it!

lazyoft commented May 13, 2016

Hi @remojansen thanks for the reply. Looking forward to it!

@remojansen

This comment has been minimized.

Show comment
Hide comment
@remojansen

remojansen Jul 27, 2016

Member

I'm closing this but this will be implemented. The implementation ticket is #307.

Member

remojansen commented Jul 27, 2016

I'm closing this but this will be implemented. The implementation ticket is #307.

@remojansen remojansen closed this Jul 27, 2016

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