janl commented on issue #756: Make couch_peruser a proper Erlang app URL: https://github.com/apache/couchdb/pull/756#issuecomment-334919162 I?ve done a bit of further research on this code and I think I?ve come up with a decent plan forward. I?m writing it down here for my own benefit, to see if I have all the missing parts, and for @chewbranca and @nickva to +1 the plan. I?ve identified two independent issues with this module, both stem from it being fundamentally being designed for CouchDB 1.x and the 2.x port being done rather haphazardly in the past (by me). **Problem No. 1:** this module gets started on each node in a cluster, each listening to `_changes` on `_users` and each trying to create the associated db. This can lead to conflicts on the `_dbs` db, which isn?t a fun situation as per @chewbranca above. **Problem No. 2:** this module doesn?t handle the case of the node it being run on failing and restarting. This is less an issue, if Problem No. 1 isn?t solved yet, as in a typical cluster there are at least two more instances of this module running that could create the database. But say we fix Problem No. 1 (as outlined above) so that each user creation will only ever result in a single attempt to create the associated database. Then, what should happen if in between picking up the notification to create the database and doing the DB creation, the current node becomes unavailable? The module currently opens `_changes` on startup and asserts all user/db creations corresponding to the `_users` db. That is, if there are 100k users, on startup, the module will try to create 100k databases, even if they already exist. A solution to this would be to add per-node high-watermark `_local/` docs, so we can more efficiently resume, but I?ll keep this as out of scope for this PR. * * * ### Solution The solution to Problem No. 1 as outline by @nickva is to re-use the replicator?s code that makes sure a replication is only run on a single node (and specifically on the node that handles the shard that the `_replicator` document is part of. All of this is neatly encapsulated in the `couch_replicator_clustering` module. That module is structured in a way that it can tell, given a `DbName` and a `DocId`, which active node in a cluster should handle a given action (replication by default, but we want user creation). All nodes participating will independently come to the same conclusion, ensuring an operation is only handled once. I propose to keep the behaviour of running the peruser module on each node in the cluster, but modify it?s changes handler to make use of `couch_replicator_clustering`?s ability to decide which node should handle an incoming user creation/deletion, since at that point, we do have the same input as the replicator code has. One concern is the use of `couch_replicator_clustering` outside of the replicator. We should make this a standalone module, but at the moment it depends on some other replicator infrastructure (`couch_replicator_notifier`) and I?d say it is out of scope to make things more generic. That probably means we must make sure that peruser is loaded after the replicator. ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected]
With regards, Apache Git Services
