cujojs / wire

A light, fast, flexible Javascript IOC container

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

context.destroy() does not trigger destroylistener appropriately

warmuuh opened this issue · comments

developing a plugin, i was unittesting my destroy listener using this code:

wire(spec, {require:require}).then(function(ctx){
//get a bean
ctx.destroy().then(function(){
//assert something on the bean
});
}, console.error);

it seems that the destroy listener are not called appropriately. (though in my normal code, they ARE called somewhen...)

Hey @warmuuh, I may not understand the case you're talking about. I added a unit test for the case I thought you meant, and it passes, so I think I need some help in understanding your situation. Could you provide (preferably) a runnable example, or at least more detail in the case above? For example, could you show the contents of the spec and an assertion you expect would pass, but instead fails?

Thanks!

Also, I just remembered this test, which verifies that the component lifecycle listeners, including component destroy listeners, are invoked at the appropriate times.

Component lifecycle listeners are notified for each component's lifecycle transitions, and context lifecycle listeners are notified for for the overall context's lifecycle transitions. AFAICT, both seem to be working correctly.

Hmmm, the wire plugin format changed in 0.10. I wonder if that is causing issues, since you're working on a plugin.

In wire < 0.10, a plugin looked like this:

{
    wire$plugin: function(options, ready, destroyed) {
        // return plugin instance
    }
}

And in 0.10 the new format is preferred (we try to support the old format, but it's possible there is a bug):

function(options) {
    // return plugin instance
}

So, instead of being an object with a wire$plugin property, plugins are now just a function that accepts options.

Also noticed that the ready and destroyed promises are no longer passed in. While they were simple to use, they introduced some potential problems and race conditions between plugins. Those promises have been replaced by a new context event listener system, which provides more events, and fixes all the problems with the potential race conditions.

Here's a quick example of a plugin that uses context event listeners:

function(options) {
    return {
        context: {
            initialize: function(resolver, wire) {
                // the context is being initialized, but no wiring has occurred yet. 
            },
            ready: function(resolver, wire) {
                // the context is ready
            }
            shutdown: function(resolver, wire) {
                // the context is **entering** the destroy phase.  It has not
                // yet been destroyed, but is about to be!
            },
            destroy: function(resolver, wire) {
                // the context has been destroyed
            }
        }
        // More plugin stuff here
    };
}

So, for example, if you had previously been relying on the destroyed promise, like this:

{
    wire$plugin: function(options, ready, destroyed) {
        destroyed.then(function() {
            // Do cleanup
        });
    }
}

You can refactor it to:

function(options) {
    return {
        context: {
            destroy: function(resolver, wire) {
                // Do cleanup, and then
                resolver.resolve();

                // Or, if you need to cleanup asynchronously:
                doAsynchronousCleanup().then(resolver.resolve, resolver.reject);
            }
        }
    };
}

Let me know if that helps. If not, please provide more detail if you can. Thanks!

well, i was using the shutdown listener instead of the destroy listener. it does not seem to work as expected anymore, or does it? :D

code:

      //testplugin.js
     module.exports = function() {
       return {'shutdown':function(r){
                           console.log("test");  
                             r.resolve();
                           }
                 }
     }

and the wiring:

    var spec = {
        bean: "test",
        $plugins: [{module:'./testplugin'}]
    };

    wire(spec, {require:require}).then(function(ctx){
        var bean = ctx.bean;
        ctx.destroy().then(function(){
                test.done();
                    });

    }, console.error);

with 'destroy', it works, the test output is visible

Thanks, @warmuuh, I'll dig into it.

After a quick look back at the code an unit tests for 0.9.0 - 0.9.4, I don't see a version in that range that supported a per-component event named shutdown. Were you using 0.9.x or something earlier, like 0.8.x?

Would it work for you to use the destroy event? or perhaps destroy:before if you want to do something just before a component is destroyed. Let me know if one of those will work for you.

@warmuuh Just wondering what the status of this is. If this is still an issue, please have a look at the questions in my last comment. Thanks!

i am sorry, but i hadn't any time lately to verify the issue. but it looks like i made a mistake and it works with the destroy listener. probably i just mixed something up. sorry for the confusion :D

No problem at all. Glad it's working for you!