{"comment":{"url":"https://api.github.com/repos/pixl8/Preside-CMS/comments/9214854","html_url":"https://github.com/pixl8/Preside-CMS/commit/7df4aa3dfd78af791cb33fe630ee577383312c09#commitcomment-9214854","id":9214854,"user":{"login":"bdw429s","id":584009,"avatar_url":"https://avatars.githubusercontent.com/u/584009?v=3","gravatar_id":"","url":"https://api.github.com/users/bdw429s","html_url":"https://github.com/bdw429s","followers_url":"https://api.github.com/users/bdw429s/followers","following_url":"https://api.github.com/users/bdw429s/following{/other_user}","gists_url":"https://api.github.com/users/bdw429s/gists{/gist_id}","starred_url":"https://api.github.com/users/bdw429s/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bdw429s/subscriptions","organizations_url":"https://api.github.com/users/bdw429s/orgs","repos_url":"https://api.github.com/users/bdw429s/repos","events_url":"https://api.github.com/users/bdw429s/events{/privacy}","received_events_url":"https://api.github.com/users/bdw429s/received_events","type":"User","site_admin":false},"position":null,"line":null,"path":"","commit_id":"7df4aa3dfd78af791cb33fe630ee577383312c09","created_at":"2015-01-09T08:03:04Z","updated_at":"2015-01-09T08:03:04Z","body":">  instead of using the scope registration details of wirebox get at the wirebox instance, it takes a direct reference to the wirebox injector as a constructor argument\r\n\r\nThis pretty much defeats one of the main purposes of providers.  One of biggest uses of providers is to prevent scope-widening injection.  This means you never want to inject a dependency with a scope that's shorter than the object being injected into because the hard reference will keep it alive longer than it was supposed to be.  Even singletons such as CacheBox, WireBox, or LogBox are not infinite.  They are re-created every time the framework restarts.  Now, imagine a user object stored in session.  This user will outlive the entire framework if you reinit so you don't want the user having ANY hard references to any pieces of the framework.  Otherwise you'll reinit and create new caches, loggers, etc, but the user's injected properties are all still pointing to stale copies that may be inoperational.  Even worse, those old copies cannot be garbage collected because they are still referenced.  After reinitting several times, you can actually have multiple copies of the entire ColdBox framework trapped in memory.  Due to the complex dependency graph, just storing a single LogBox logger could in turn have references to the Controller, and from there every other CFC in the framework.\r\n\r\nThe solution was providers.  These were, by design, completely stand-alone CFCs with absolutely no hard references to anything.  They were simply armed with the knowledge of how to look up what you needed when the time arrived.  Providers can be safely injected into any CFC regardless of its scope (imagine server.something) and they have no strings attached.  Providers use the \"lookup pattern\" to find WireBox when the time comes and ask it for the current instance of whatever it needs.  This allows the dependency to be a \"moving target\" that changes over time.\r\n\r\nThis is why we can't change providers to start having hard references to WireBox.\r\n\r\nSo, as Luis said, the answer to your question of \"What about requests trying to run during a reinit?\" is basically, \"Don't do that!\".  Reinit has always been known to be not thread safe.  It basically tears the entire framework down and rebuilds it from scratch.  Getting a request to keep running during that time would be pretty tricky so the official recommendation is don't reinit on production and if you do, don't expect other requests to be able to run at the same time.  The only true way would be to remove that server from a load-balanced cluster, perform maintenance, and re-add it.\r\n\r\nThere are two approaches people have taken to mitigate this:\r\n## read/write locking\r\nIn this approach a normal request execution is wrapped in a named read lock, and a reinit acquires an exclusive lock of the same name.  Normal requests can execute as they wish until you put through for a reinit.  The reinit thread will wait until all the running requests have 'drained' out and it is the next one in line so it can get the exclusive lock.  The reinit thread then takes its sweet times while everything else piles up waiting.  When the reinit is complete, the floodgates are opened and requests being executing again.\r\n\r\nThis sounds promising but in practicality, is only possible on low-traffic sites.  Let's say your site is getting 15 request/sec and your reinit takes 1 minute.   That means 900 requests will have queued up in the mean time.  Those users are going to have a long wait, and the server will probably die once it starts letting them all back through.\r\n\r\n## Under maintenance (fail whale)\r\nThe second approach is to set some flag in memory once a reinit starts and clear that flag once it stops.  All incoming requests will just dump a message to the user saying \"try again later\" until the reinit is done.  That means 900 people will get a message, but at least they get instant feedback and the servers don't get taken down by a flood of traffic.  This approach can be combined with the locking in the previous approach to drain off the users before the reinit starts.  Be forwarned though, someone running a very long request (like a long-running report) can prevent the reinit from starting for a long time or running at all which can kind of hold your own server hostage from you were you can't get it to reinit because it's too busy.\r\n\r\n## A/B Switch\r\nSo, what you're trying is a sort of third option whereby  you keep the entire old framework in memory until the reinit is done.  While that might be possible to implement in some custom environment whereby you force conventions upon yourself or put a system in place to manage every dependency that's ever injected into a component, that's not something ColdBox is equipped to do, nor can CFML support.  Imagine our session.user.  He's been loaded up with hard references to the controller, LogBox, CacheBox, etc in his variables scope.  When the framework restarts how will you know to swap those references?  WireBox doesn't keep notes on what it's injected.  How can you even access that CFC since it's in a private session scope?  This is why Coldbox doesn't even try.  We tell you to use a provider to avoid the hard references to begin with.  \r\n\r\nI suppose something might be possible if EVERY dependency ever injected by WireBox was secretly wrapped in a provider that would internally handle an A/B switch but that would be a significant change with overhead, and compatibility issues.  For instance, you can't access public THIS.foo variables on a provider.  I can't imagine ColdBox being able to pull that off as a core feature."}}