Skip to content

Commit

Permalink
Allow bundling all available DB adapters in tinode binaries.
Browse files Browse the repository at this point in the history
In addition to specifying the DB adapter explicitly via build tags,
allow bundling all available DB adapters to the binary (enabled via "all" tag).
The adapter may be chosen by setting `store_config.adapter_name` field in `tinode.conf`.

Modify build scripts and docker configs to support this.
Docker tinode-all image includes the bundled binaries, the adapter may be
chosen by providing ADAPTER_NAME env var.
  • Loading branch information
aforge committed Mar 9, 2020
1 parent e8f149c commit 931bf41
Show file tree
Hide file tree
Showing 17 changed files with 73 additions and 19 deletions.
18 changes: 16 additions & 2 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ See [instructions](./docker/README.md)
go get -tags mongodb github.com/tinode/chat/server && go build -tags mongodb -o $GOPATH/bin/tinode github.com/tinode/chat/server
go get -tags mongodb github.com/tinode/chat/tinode-db && go build -tags mongodb -o $GOPATH/bin/init-db github.com/tinode/chat/tinode-db
```
- **All** (bundle all the above DB adapters):
```
go get -tags all github.com/tinode/chat/server && go build -tags all -o $GOPATH/bin/tinode github.com/tinode/chat/server
go get -tags all github.com/tinode/chat/tinode-db && go build -tags all -o $GOPATH/bin/init-db github.com/tinode/chat/tinode-db
```

Note the required **`-tags rethinkdb`**, **`-tags mysql`** or **`-tags mongodb`** build option.
Note the required **`-tags rethinkdb`**, **`-tags mysql`**, **`-tags mongodb`** or **`-tags all`** build option.

You may also optionally define `main.buildstamp` for the server by adding a build option, for instance, with a timestamp:
```
Expand All @@ -64,7 +69,16 @@ See [instructions](./docker/README.md)
},
```

5. Now that you have built the binaries, follow instructions in the _Running a Standalone Server_ section.
5. If you bundling all available DB adapters in the Tinode binary, make sure you specify the adapter name in your `tinode.conf`. E.g. you want to run Tinode with MySQL:
```js
"store_config: {
...
"adapter_name": "mysql",
...
},
```
6. Now that you have built the binaries, follow instructions in the _Running a Standalone Server_ section.
## Running a Standalone Server
Expand Down
2 changes: 1 addition & 1 deletion build-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ goplat=( darwin windows linux )
# Supported CPU architectures: amd64
goarc=( amd64 )
# Supported database tags
dbtags=( mysql mongodb rethinkdb )
dbtags=( mysql mongodb rethinkdb all )

for line in $@; do
eval "$line"
Expand Down
2 changes: 1 addition & 1 deletion docker-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if [[ ${ver[2]} != *"-"* ]]; then
FULLRELEASE=1
fi

dbtags=( mysql mongodb rethinkdb )
dbtags=( mysql mongodb rethinkdb all )

# Build an images for various DB backends
for dbtag in "${dbtags[@]}"
Expand Down
2 changes: 1 addition & 1 deletion docker-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ if [[ ${ver[2]} != *"-"* ]]; then
FULLRELEASE=1
fi

dbtags=( mysql mongodb rethinkdb )
dbtags=( mysql mongodb rethinkdb all )

# Read dockerhub login/password from a separate file
source .dockerhub
Expand Down
9 changes: 8 additions & 1 deletion docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ All images are available at https://hub.docker.com/r/tinode/
$ docker network create tinode-net
```

3. Decide which database backend you want to use: RethinkDB or MySQL. Run the selected database container, attaching it to `tinode-net` network:
3. Decide which database backend you want to use: RethinkDB, MySQL or MongoDB. Run the selected database container, attaching it to `tinode-net` network:

1. **RethinkDB**: If you've decided to use RethinkDB backend, run the official RethinkDB Docker container:
```
Expand Down Expand Up @@ -53,6 +53,11 @@ All images are available at https://hub.docker.com/r/tinode/
$ docker run -p 6060:18080 -d --name tinode-srv --network tinode-net tinode/tinode-mongodb:latest
```

You can also run Tinode with the `tinode/tinode-all` image (which has all of the above DB adapters compiled in). You will need to specify the database adapter using the `ADAPTER_NAME` environment variable. E.g. for `mysql`, the command line will look like
```
$ docker run -p 6060:18080 -d -e ADAPTER_NAME mysql --name tinode-srv --network tinode-net tinode/tinode-all:latest
```

See [below](#supported-environment-variables) for more options.

The port mapping `-p 6060:18080` tells Docker to map container's port 18080 to host's port 6060 making server accessible at http://localhost:6060/. The container will initialize the database with test data on the first run.
Expand All @@ -61,6 +66,7 @@ All images are available at https://hub.docker.com/r/tinode/
* [MySQL tags](https://hub.docker.com/r/tinode/tinode-mysql/tags/)
* [RethinkDB tags](https://hub.docker.com/r/tinode/tinode-rethink/tags/)
* [MongoDB tags](https://hub.docker.com/r/tinode/tinode-mongodb/tags/) (comming soon)
* [All bundle tags](https://hub.docker.com/r/tinode/tinode-all/tags/) (comming soon)

5. Test the installation by pointing your browser to [http://localhost:6060/](http://localhost:6060/).

Expand Down Expand Up @@ -127,6 +133,7 @@ You can specify the following environment variables when issuing `docker run` co

| Variable | Type | Default | Function |
| --- | --- | --- | --- |
| `ADAPTER_NAME` | string | | DB adapter name (use with `tinode/tinode-all` container only) |
| `AUTH_TOKEN_KEY` | string | `wfaY2RgF2S1OQI/ZlK+LS​rp1KB2jwAdGAIHQ7JZn+Kc=` | base64-encoded 32 random bytes used as salt for authentication tokens. |
| `AWS_ACCESS_KEY_ID` | string | | AWS Access Key ID when using `s3` media handler |
| `AWS_CORS_ORIGINS` | string | `["*"]` | Allowed origins ([CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)) URL for downloads. Generally use your server URL and its aliases. |
Expand Down
3 changes: 3 additions & 0 deletions docker/tinode/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ ENV FCM_PUSH_ENABLED=false
# Enable Android-specific notifications by default.
ENV FCM_INCLUDE_ANDROID_NOTIFICATION=true

# Use the default adapter.
ENV ADAPTER_NAME=""

# Install root certificates, they are needed for email validator to work
# with the TLS SMTP servers like Gmail. Also add bash and grep.
RUN apk update && \
Expand Down
1 change: 1 addition & 0 deletions docker/tinode/config.template
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

"store_config": {
"uid_key": "$UID_ENCRYPTION_KEY",
"adapter_name": "$ADAPTER_NAME",
"adapters": {
"mysql": {
"database": "tinode",
Expand Down
2 changes: 1 addition & 1 deletion server/db/mongodb/adapter.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build mongodb
// +build mongodb all

// Package mongodb is a database adapter for MongoDB.
package mongodb
Expand Down
2 changes: 1 addition & 1 deletion server/db/mongodb/blank.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !mongodb
// +build !mongodb,!all

// This file is needed for conditional compilation. It's used when
// the build tag 'mongodb' is not defined. Otherwise the adapter.go
Expand Down
2 changes: 1 addition & 1 deletion server/db/mysql/adapter.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build mysql
// +build mysql all

// Package mysql is a database adapter for MySQL.
package mysql
Expand Down
2 changes: 1 addition & 1 deletion server/db/mysql/blank.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !mysql
// +build !mysql,!all

// This file is needed for conditional compilation. It's used when
// the build tag 'mysql' is not defined. Otherwise the adapter.go
Expand Down
2 changes: 1 addition & 1 deletion server/db/rethinkdb/adapter.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build rethinkdb
// +build rethinkdb all

// Package rethinkdb s a database adapter for RethinkDB.
package rethinkdb
Expand Down
2 changes: 1 addition & 1 deletion server/db/rethinkdb/blank.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !rethinkdb
// +build !rethinkdb,!all

// This file is needed for conditional compilation. It's used when
// the build tag 'rethinkdb' is not defined. Otherwise the adapter.go
Expand Down
5 changes: 3 additions & 2 deletions server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ func main() {
// Absolute paths are left unchanged.
rootpath, _ := filepath.Split(executable)

log.Printf("Server v%s:%s:%s; db: '%s'; pid %d; %d process(es)",
log.Printf("Server v%s:%s:%s; pid %d; %d process(es)",
currentVersion, executable, buildstamp,
store.GetAdapterName(), os.Getpid(), runtime.GOMAXPROCS(runtime.NumCPU()))
os.Getpid(), runtime.GOMAXPROCS(runtime.NumCPU()))

var configfile = flag.String("config", "tinode.conf", "Path to config file.")
// Path to static content.
Expand Down Expand Up @@ -332,6 +332,7 @@ func main() {
if err != nil {
log.Fatal("Failed to connect to DB: ", err)
}
log.Println("DB adapter", store.GetAdapterName())
defer func() {
store.Close()
log.Println("Closed database connection(s)")
Expand Down
31 changes: 26 additions & 5 deletions server/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package store
import (
"encoding/json"
"errors"
"log"
"sort"
"strings"
"time"
Expand All @@ -16,6 +17,7 @@ import (
)

var adp adapter.Adapter
var availableAdapters map[string]adapter.Adapter = make(map[string]adapter.Adapter)
var mediaHandler media.Handler

// Unique ID generator
Expand All @@ -26,6 +28,10 @@ type configType struct {
UidKey []byte `json:"uid_key"`
// Maximum number of results to return from adapter.
MaxResults int `json:"max_results"`
// DB adapter name to use. Should be one of these specified in `Adapters`.
// If empty and `Adapters` contains only one record, the server will default
// to this only record in `Adapters`.
AdapterName string `json:"adapter_name"`
// Configurations for individual adapters.
Adapters map[string]json.RawMessage `json:"adapters"`
}
Expand All @@ -37,7 +43,22 @@ func openAdapter(workerId int, jsonconf json.RawMessage) error {
}

if adp == nil {
return errors.New("store: database adapter is missing")
if len(config.AdapterName) > 0 {
// Adapter name specified explicitly.
if ad, ok := availableAdapters[config.AdapterName]; ok {
adp = ad
} else {
return errors.New("store: " + config.AdapterName + " adapter is not available in this binary")
}
} else if len(availableAdapters) == 1 {
// Attempt to default to the only entry in availableAdapters.
for _, v := range availableAdapters {
adp = v
}
log.Println("store: db adapter not specified explicitly; using", adp.GetName())
} else {
return errors.New("store: db adapter is neither specified explicitly nor can be deduced from the available adapters")
}
}

if adp.IsOpen() {
Expand Down Expand Up @@ -154,11 +175,11 @@ func RegisterAdapter(a adapter.Adapter) {
panic("store: Register adapter is nil")
}

if adp != nil {
panic("store: adapter '" + adp.GetName() + "' is already registered")
adapterName := a.GetName()
if _, ok := availableAdapters[adapterName]; ok {
panic("store: adapter '" + adapterName + "' is already registered")
}

adp = a
availableAdapters[adapterName] = a
}

// GetUid generates a unique ID suitable for use as a primary key.
Expand Down
6 changes: 6 additions & 0 deletions server/tinode.conf
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@
// Maximum number of results fetched in one DB call.
"max_results": 1024,

// DB adapter name to communicate with the DB backend.
// Must be either one of the adapters from the list below, or empty -
// in which case the server will attempt to default to the adapter
// explicitly specified via build tags at build time.
"adapter_name": "",

// Configurations of individual adapters.
"adapters": {
// MySQL configuration. See https://godoc.org/github.com/go-sql-driver/mysql#Config
Expand Down
1 change: 1 addition & 0 deletions tinode-db/tinode.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"store_config": {
"uid_key": "la6YsO+bNX/+XIkOqc5Svw==",
"adapter_name": "",
"adapters": {
"mysql": {
"database": "tinode",
Expand Down

0 comments on commit 931bf41

Please sign in to comment.