github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/docs/archives/couchdb-plugins.md (about) 1 [Table of contents](../README.md#table-of-contents) 2 3 This document was written in october 2016. 4 5 # Couchdb plugins analysis 6 7 (original discussion is at https://github.com/cozy/cozy-stack/issues/9) 8 9 ## Existing packages 10 11 ### https://github.com/timjacobi/go-couchdb 12 13 - last edit 2016-08 14 - Apparently one of the firsts 15 - Includes a http module, trying to figure out why, might simply be history 16 (started in 2014) 17 - fork of the "original" https://github.com/fjl/go-couchdb 18 - brother of https://github.com/pokstad/go-couchdb which is used in this cool 19 article : http://pokstad.com/2015/04/18/couchdb-and-go.html 20 - Have tools to run as couchdbapp / couchdbdaemon (we wont use these) 21 - Allow to pass a net/http.RoundTripper for fine transport tunning. 22 - Pr merged with some fix for couchdb2, not sure if there is more issue 23 24 ### https://github.com/zemirco/couchdb 25 26 - last edit 2016-08 27 - No functions for changes API 28 - Have a special interface for document {GetID(), GetRev()} 29 30 ### https://github.com/rhinoman/couchdb-go 31 32 - last edit 2016-04 33 - No functions for changes API 34 - Have functions for managing users and roles 35 - Have functions for proxying requests (downloads / uploads) 36 - support json byte[] as well as interface{} for documents 37 - Is clean and clear, but more complex because of more functions. We will need 38 most those (users, proxy) 39 40 ### https://github.com/dustin/go-couch 41 42 - last edit 2016-08 43 - Simplest 44 45 ## Plan B - Make our own from net/http 46 47 If we go this way, it will be a good idea to look at the code of the other 48 packages for each function, some pitfalls could be avoided : 49 50 ex: 51 52 - https://github.com/rhinoman/couchdb-go/blob/94e6ab663d5789615eb061b52ed2e67310bac13f/connection.go#L81 53 - Use custom Director & httputil.ReverseProxy for file download / upload 54 55 ## Considerations on how we will use it 56 57 (see the [architecture](architecture.md) for more info) 58 59 - One stack instance communicate with one couchdb 2.x server or cluster. The 60 couchdb server/cluster has a lot of databases (nb_users x nb_data_types). 61 The pair stack+couch should handle as many active users as possible. Number 62 of unactive users must not impact perfs too much. Note : definition of 63 active user TBD (mobile app and 3rd party software are syncing using \*dav 64 and some background jobs like fetching banks accounts and threshold alerts ) 65 - HTTPS between stack and couchdb is not a priority. If it's an option, it 66 will allow more flexibility for ops team, but we can always find alternative 67 solution to secure channel between stack and couchdb and self-hosted users 68 will probably have both on an single machine. 69 - We wont keep changes feed open, as it was identified in couchdb workshop as 70 the limiting factor on number of databases we can have and we want to have a 71 bazillion databases. We will probably do some kind of polling, this will 72 need to be investigated deeper. 73 - Binaries will NOT be stored in couchdb. We will only store in couchdb 74 reference to the file in another storage solution (FS / Swift) 75 - The stack will use couchdb in 2 ways : 76 1. Just proxying to/from the client, we will still need to parse the JSON, 77 but will only read or changes a few special fields (`_id`, `_type`, 78 `_tags` ....) for ACL and then pipe it to/from couchdb. We wont need to 79 make sense of the whole document and can eventually get away without 80 parsing it on some routes. This part should be totally flexible on the 81 json content. 82 2. Some APIs and Jobs will need to make sense of the given documents, so 83 (un)marshal them from/into smarter struct (CalendarEvent) to be used in 84 business logic. 85 86 ## Analysis 87 88 - They are all relatively similar in term of API. rhinoman has some more 89 functions that we will need but lack changes feed. 90 - They all have a struct for database which hold configuration, as most of our 91 request will be on different databases, we will have a great churn for these 92 structure. This is less than optimal for RAM & GC, but probably 93 insignificant against JSON parsing. 94 - They all use JSON Marshal et encode to accept any interface{} as couchdb 95 doc. 96 - They are all relatively inactive / stable, not sure if it is because they 97 are "finished" or abandonware. 98 - No library has a notion of pooling connection. This is handled at the 99 net/http.Transport level in golang. 100 - Only the first library has option for fine-tunning of the internal 101 Client/Transport, 102 - No library support couchdb2 mango 103 104 ## Going further (thanks @tomquest) 105 106 Another advantage of a DIY solution: building exactly what `stack` needs. This 107 is orienting the CouchDB access code for Cozy usage. And this could be 108 implemented as a **DSL**. 109 110 For example: _(if I understand the architecture, the goal is for an User to have 111 many Databases, one for each DocumentType)_ 112 113 ```go 114 // Create an Email 115 couchdb 116 .Doc(anEmail) // deduce the database from the type of the parameters 117 .Create() 118 // .Update() 119 // .Delete() 120 ``` 121 122 ```go 123 // List emails from 100 to 200 124 emails = couchdb 125 .emails() // pick the appropriate database 126 .Offset(100) 127 .Limit(200) 128 .Order(DATE, DESC) 129 .select() // Create the adhoc CouchDb query (`Mango` style ?) 130 ``` 131 132 BTW, `couchdb` could be an already configured object with the appropriate user 133 credentials. 134 135 Pros: 136 137 - Cozy-stack oriented (functionally) 138 - Still able to access CouchDb natively (eg. `couchdb.Connection()`) 139 - Can hide technical stuff: access to the pool, concurrency, caching, https, 140 retries, timeouts... 141 - Build and maintained by Cozy 142 143 Cons: 144 145 - DSL to write (and testing is a bit harder) 146 - To be maintained, but in fact, this is already the case for the other 147 wrappers 148 149 ## Current decision 150 151 We will make our own driver by cherry picking relevant codes in other libraries.