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.