{"action":"created","issue":{"url":"https://api.github.com/repos/aio-libs/aiohttp/issues/2689","repository_url":"https://api.github.com/repos/aio-libs/aiohttp","labels_url":"https://api.github.com/repos/aio-libs/aiohttp/issues/2689/labels{/name}","comments_url":"https://api.github.com/repos/aio-libs/aiohttp/issues/2689/comments","events_url":"https://api.github.com/repos/aio-libs/aiohttp/issues/2689/events","html_url":"https://github.com/aio-libs/aiohttp/issues/2689","id":291686311,"number":2689,"title":"Sharing db connection to nested nested app","user":{"login":"fduxiao","id":9294979,"avatar_url":"https://avatars0.githubusercontent.com/u/9294979?v=4","gravatar_id":"","url":"https://api.github.com/users/fduxiao","html_url":"https://github.com/fduxiao","followers_url":"https://api.github.com/users/fduxiao/followers","following_url":"https://api.github.com/users/fduxiao/following{/other_user}","gists_url":"https://api.github.com/users/fduxiao/gists{/gist_id}","starred_url":"https://api.github.com/users/fduxiao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fduxiao/subscriptions","organizations_url":"https://api.github.com/users/fduxiao/orgs","repos_url":"https://api.github.com/users/fduxiao/repos","events_url":"https://api.github.com/users/fduxiao/events{/privacy}","received_events_url":"https://api.github.com/users/fduxiao/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2018-01-25T19:24:47Z","updated_at":"2018-02-01T09:14:37Z","closed_at":null,"author_association":"NONE","body":"## Long story short\r\n\r\nI've read  your answer in #2413 (raised in #2412 ).\r\nThe solution (`subapp['db'] = mainapp['db']`) does not work when it comes to nested subapps.\r\nFor example, if I have to build an app A, which have some subapp B and I need to pass the db connection from A to B, which can be done in that behavior. But, when I need to nest app A as a subapp to C, another app, and how should I pass db from C to A and to B. Clearly, the sharing between A and B exists before that between C and A, when A does not know the existence of db (which is even set inside startup) and C should also know nothing about the inner structure of A. A more complicated mechanism should be provided. \r\n\r\n## Expected behaviour\r\n\r\nA more complicated solution. \r\n\r\n## Actual behaviour\r\n\r\nToo simple to solve the problem. \r\n\r\n## Steps to reproduce\r\n\r\n```python\r\nfrom aiohttp import web\r\n\r\napp_b = web.Application()\r\n\r\napp_a = web.Application()\r\napp_b['db'] = app_a['db']  # error\r\napp_a.add_subapp('/b', app_b)\r\n\r\napp_c = web.Application()\r\napp_c['db'] = 'db'  # actually inside a startup event\r\napp_c.add_subapp('/a', app_a)  # how should I pass app_c['db']\r\n\r\nweb.run_app(app_c)\r\n\r\n```\r\n## My solution\r\nI'm trying to solve the problem by making the db become a `promise` (or a monad, which makes more sense about the side effect of the main app on the sub app ?). \r\n```python\r\nfrom aiohttp import web\r\n\r\n\r\nclass MyApplication(web.Application):\r\n\r\n    get_db = None\r\n\r\n    def set_db(self, db):\r\n        self.get_db = lambda: db\r\n\r\n    def add_subapp(self, prefix, subapp):\r\n        # The db should be a `promise` (like a monad).\r\n        # When the `db` property is called,\r\n        # the promise is then calculated.\r\n        # So, when the db is set, a promise is set,\r\n        # and when it is passed to the subapp, the promise is passed\r\n\r\n        async def set_db(app):\r\n            app.get_db = lambda: self.get_db()\r\n        subapp.on_startup.append(set_db)\r\n        #  subapp.get_db = lambda: self.get_db()\r\n        return super().add_subapp(prefix, subapp)\r\n\r\n```\r\nWhile flask provides a `g` so I can share the db between different apps (with in the same request), will you consider adding a same mechanism (or a monadic implementation if your consider about the implicit `side effect` introduced by `g`), since not only the db is shared(more data should be shared?).\r\n"},"comment":{"url":"https://api.github.com/repos/aio-libs/aiohttp/issues/comments/362204567","html_url":"https://github.com/aio-libs/aiohttp/issues/2689#issuecomment-362204567","issue_url":"https://api.github.com/repos/aio-libs/aiohttp/issues/2689","id":362204567,"user":{"login":"asvetlov","id":356399,"avatar_url":"https://avatars0.githubusercontent.com/u/356399?v=4","gravatar_id":"","url":"https://api.github.com/users/asvetlov","html_url":"https://github.com/asvetlov","followers_url":"https://api.github.com/users/asvetlov/followers","following_url":"https://api.github.com/users/asvetlov/following{/other_user}","gists_url":"https://api.github.com/users/asvetlov/gists{/gist_id}","starred_url":"https://api.github.com/users/asvetlov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/asvetlov/subscriptions","organizations_url":"https://api.github.com/users/asvetlov/orgs","repos_url":"https://api.github.com/users/asvetlov/repos","events_url":"https://api.github.com/users/asvetlov/events{/privacy}","received_events_url":"https://api.github.com/users/asvetlov/received_events","type":"User","site_admin":false},"created_at":"2018-02-01T09:14:37Z","updated_at":"2018-02-01T09:14:37Z","author_association":"OWNER","body":"Both snippets are identical and both generate KeyError exception"}}
{"actor":{"display_login":"asvetlov"}}