Skip to content

Commit 9576cae

Browse files
committed
simplifying configs to fix a bug with worker id
1 parent c3f1428 commit 9576cae

File tree

11 files changed

+191
-249
lines changed

11 files changed

+191
-249
lines changed

INSTALL.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The value of `buildstamp` will be sent by the server to the clients.
2828

2929
## Running a Standalone Server
3030

31+
3132
1. Run RethinkDB:
3233
```
3334
rethinkdb --bind all --daemon
@@ -48,7 +49,7 @@ The value of `buildstamp` will be sent by the server to the clients.
4849

4950
4. Run server
5051
```
51-
$GOPATH/bin/server -config=$GOPATH/src/github.com/tinode/chat/server/tinode.conf-example -static_data=$HOME/tinode/example-react-js/
52+
$GOPATH/bin/server -config=$GOPATH/src/github.com/tinode/chat/server/tinode.conf -static_data=$HOME/tinode/example-react-js/
5253
```
5354

5455
5. Test your installation by pointing your browser to [http://localhost:6060/x/](http://localhost:6060/x/). Keep in mind that by default the static files from the `-static_data` path are served at `/x/`. You can change this by editing the line `static_mount` in the config file.
@@ -59,16 +60,18 @@ The value of `buildstamp` will be sent by the server to the clients.
5960

6061
- Install RethinkDB, run it stanalone or in [cluster mode](https://www.rethinkdb.com/docs/start-a-server/#a-rethinkdb-cluster-using-multiple-machines). Run DB initializer, unpack JS files as described in the previous section.
6162

62-
- Cluster expects at least two nodes. A minimum of three nodes is recommended. A sample cluster config file is provided as `cluster.conf`. The following section configures the cluster.
63+
- Cluster expects at least two nodes. A minimum of three nodes is recommended.
64+
65+
- The following section configures the cluster.
6366

6467
```
6568
"cluster_config": {
69+
"self": "",
6670
"nodes": [
6771
{"name": "one", "addr":"localhost:12001"},
6872
{"name": "two", "addr":"localhost:12002"},
6973
{"name": "three", "addr":"localhost:12003"}
7074
],
71-
"self": "one",
7275
"failover": {
7376
"enabled": true,
7477
"heartbeat": 100,
@@ -77,8 +80,8 @@ The value of `buildstamp` will be sent by the server to the clients.
7780
}
7881
}
7982
```
83+
* `self` is the name of the current node. Generally it's more convenient to specify the name of the current node at the command line using `cluster_self` option. Command line value overrides the config file value. If the value is not provided either in the config file or through the command line, the clustering is disabled.
8084
* `nodes` defines individual cluster nodes. The sample defines three nodes named `one`, `two`, and `tree` running at the localhost at the specified cluster communication ports. Cluster addresses don't need to be exposed to the outside world.
81-
* `self` is the name of the current node. Generally it's more convenient to specify the name of the current node at the command line using `cluster_self` option. Command line value overrides the config file value.
8285
* `failover` is an experimental feature which migrates topics from failed cluster nodes keeping them accessible:
8386
* `enabled` turns on failover mode; failover mode requires at least three nodes in the cluster.
8487
* `heartbeat` interval in milliseconds between heartbeats sent by the leader node to follower nodes to ensure they are accessible.
@@ -87,8 +90,8 @@ The value of `buildstamp` will be sent by the server to the clients.
8790

8891
If you are testing the cluster with all nodes running on the same host, you also must override the `listen` port. Here is an example for launching two cluster nodes from the same host using the same config file:
8992
```
90-
./server -config=./cluster.conf -static_data=./example-react-js/ -listen=:6060 -cluster_self=one &
91-
./server -config=./cluster.conf -static_data=./example-react-js/ -listen=:6061 -cluster_self=two &
93+
./server -config=./tinode.conf -static_data=./example-react-js/ -listen=:6060 -cluster_self=one &
94+
./server -config=./tinode.conf -static_data=./example-react-js/ -listen=:6061 -cluster_self=two &
9295
```
9396

9497
### Note on Running the Server in Background
@@ -112,14 +115,12 @@ For more details see https://github.com/tinode/chat/issues/25.
112115

113116
2. Make sure MySQL (or MariaDB or Percona) is installed and running. The code has been tested with MySQL 5.7 but should work with earlier versions as well.
114117

115-
3. Rename `tinode.conf-example` to `tinode.conf`
116-
117-
4. Open `tinode.conf`. In the section `"store_config"` find `"use_adapter": "rethinkdb"` and replace it with `"use_adapter": "mysql"`. Check that the [DSN](https://github.com/go-sql-driver/mysql#dsn-data-source-name) in `"mysql"` section is appropriate for your MySQL installation. Option `parseTime=true` is required.
118+
3. Open `tinode.conf`. In the section `"store_config"` find `"use_adapter": "rethinkdb"` and replace it with `"use_adapter": "mysql"`. Check that the [DSN](https://github.com/go-sql-driver/mysql#dsn-data-source-name) in `"mysql"` section is appropriate for your MySQL installation. Option `parseTime=true` is required.
118119
```js
119120
"mysql": {
120121
"dsn": "root@tcp(localhost)/tinode?parseTime=true",
121122
"database": "tinode"
122123
},
123124
```
124125

125-
5. Follow the instructions for running as a standalone server from step 2.
126+
4. Follow the instructions for running as a standalone server from step 2.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ A text-only [command line client](./tn-cli) implements every possible command.
2626

2727
* User `Tino` is a [basic chatbot](./chatbot) which responds with a [random quote](http://fortunes.cat-v.org/) to any message.
2828

29-
* When you register a new account you are asked for an email. Usually the email is expected be verified by sending a message with a code but the demo server is configured not to send anything to the given email. It will accept `123456` as a verification code instead.
29+
* As generally accepted, when you register a new account you are asked for an email address. The server will send an email with a verification code to that address and you can use it to validate the account. To make things easier for testing, the server will also accept `123456` as a verification code. Remove line `"debug_response": "123456"` from `tinode.conf` to disable this option.
3030

3131
* The demo server is configured to use [ACME](https://letsencrypt.org/) TLS [implementation](https://godoc.org/golang.org/x/crypto/acme) with hard-coded requirement for [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication). If you are unable to connect then the most likely reason is your TLS client's missing support for SNI. Use a different client.
3232

server/auth/token/auth_token.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (ta *authenticator) Init(jsonconf string) error {
6262
return errors.New("auth_token: failed to parse config: " + err.Error() + "(" + jsonconf + ")")
6363
}
6464

65-
if config.Key == nil || len(config.Key) < tokenMinHmacLength {
65+
if len(config.Key) < tokenMinHmacLength {
6666
return errors.New("auth_token: the key is missing or too short")
6767
}
6868
if config.ExpireIn <= 0 {

server/cluster.go

Lines changed: 59 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log"
88
"net"
99
"net/rpc"
10+
"sort"
1011
"sync"
1112
"time"
1213

@@ -258,6 +259,9 @@ type Cluster struct {
258259
// Name of the local node
259260
thisNodeName string
260261

262+
// Resolved address to listed on
263+
listenOn string
264+
261265
// Socket for inbound connections
262266
inbound *net.TCPListener
263267
// Ring hash for mapping topic names to nodes
@@ -414,37 +418,47 @@ func (c *Cluster) sessionGone(sess *Session) error {
414418
return nil
415419
}
416420

417-
func clusterInit(configString json.RawMessage, self *string) {
421+
// Returns snowflake worker id
422+
func clusterInit(configString json.RawMessage, self *string) int {
418423
if globals.cluster != nil {
419-
log.Fatal("Cluster already initialized")
424+
log.Fatal("Cluster already initialized.")
420425
}
421426

422427
// This is a standalone server, not initializing
423-
if configString == nil || len(configString) == 0 {
428+
if len(configString) == 0 {
424429
log.Println("Running as a standalone server.")
425-
return
430+
return 1
426431
}
427432

428433
var config clusterConfig
429434
if err := json.Unmarshal(configString, &config); err != nil {
430435
log.Fatal(err)
431436
}
432437

433-
gob.Register([]interface{}{})
434-
gob.Register(map[string]interface{}{})
435-
436438
thisName := *self
437439
if thisName == "" {
438440
thisName = config.ThisName
439441
}
442+
443+
// Name of the current node is not specified - disable clustering
444+
if thisName == "" {
445+
log.Println("Running as a standalone server.")
446+
return 1
447+
}
448+
449+
gob.Register([]interface{}{})
450+
gob.Register(map[string]interface{}{})
451+
440452
globals.cluster = &Cluster{
441453
thisNodeName: thisName,
442454
nodes: make(map[string]*ClusterNode)}
443455

444-
listenOn := ""
456+
var nodeNames []string
445457
for _, host := range config.Nodes {
446-
if host.Name == globals.cluster.thisNodeName {
447-
listenOn = host.Addr
458+
nodeNames = append(nodeNames, host.Name)
459+
460+
if host.Name == thisName {
461+
globals.cluster.listenOn = host.Addr
448462
// Don't create a cluster member for this local instance
449463
continue
450464
}
@@ -453,7 +467,6 @@ func clusterInit(configString json.RawMessage, self *string) {
453467
address: host.Addr,
454468
name: host.Name,
455469
done: make(chan bool, 1)}
456-
go n.reconnect()
457470

458471
globals.cluster.nodes[host.Name] = &n
459472
}
@@ -467,21 +480,10 @@ func clusterInit(configString json.RawMessage, self *string) {
467480
globals.cluster.rehash(nil)
468481
}
469482

470-
addr, err := net.ResolveTCPAddr("tcp", listenOn)
471-
if err != nil {
472-
log.Fatal(err)
473-
}
474-
475-
globals.cluster.inbound, err = net.ListenTCP("tcp", addr)
476-
if err != nil {
477-
log.Fatal(err)
478-
}
479-
480-
rpc.Register(globals.cluster)
481-
go rpc.Accept(globals.cluster.inbound)
483+
sort.Strings(nodeNames)
484+
workerId := sort.SearchStrings(nodeNames, thisName) + 1
482485

483-
log.Printf("Cluster of %d nodes initialized, node '%s' listening on [%s]", len(globals.cluster.nodes)+1,
484-
globals.cluster.thisNodeName, listenOn)
486+
return workerId
485487
}
486488

487489
// This is a session handler at a master node: forward messages from the master to the session origin.
@@ -537,6 +539,38 @@ func (sess *Session) closeRPC() {
537539
}
538540
}
539541

542+
// Start accepting connections.
543+
func (c *Cluster) start() {
544+
addr, err := net.ResolveTCPAddr("tcp", c.listenOn)
545+
if err != nil {
546+
log.Fatal(err)
547+
}
548+
549+
c.inbound, err = net.ListenTCP("tcp", addr)
550+
551+
if err != nil {
552+
log.Fatal(err)
553+
}
554+
555+
for _, n := range c.nodes {
556+
go n.reconnect()
557+
}
558+
559+
if c.fo != nil {
560+
go c.run()
561+
}
562+
563+
err = rpc.Register(c)
564+
if err != nil {
565+
log.Fatal(err)
566+
}
567+
568+
go rpc.Accept(c.inbound)
569+
570+
log.Printf("Cluster of %d nodes initialized, node '%s' listening on [%s]", len(globals.cluster.nodes)+1,
571+
globals.cluster.thisNodeName, c.listenOn)
572+
}
573+
540574
func (c *Cluster) shutdown() {
541575
if globals.cluster == nil {
542576
return

server/cluster_leader.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func (c *Cluster) failoverInit(config *clusterFailoverConfig) bool {
8787
return false
8888
}
8989
if len(c.nodes) < 2 {
90-
log.Printf("cluster: failover disabled; need at least 3 nodes, got %d only", len(c.nodes)+1)
90+
log.Printf("cluster: failover disabled; need at least 3 nodes, got %d", len(c.nodes)+1)
9191
return false
9292
}
9393

@@ -114,8 +114,6 @@ func (c *Cluster) failoverInit(config *clusterFailoverConfig) bool {
114114
electionVote: make(chan *ClusterVote, len(c.nodes)),
115115
done: make(chan bool, 1)}
116116

117-
go c.run()
118-
119117
log.Println("cluster: failover mode enabled")
120118

121119
return true

server/db/mysql/adapter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ func (a *adapter) CreateDb(reset bool) error {
341341
createdat DATETIME(3) NOT NULL,
342342
updatedat DATETIME(3) NOT NULL,
343343
method VARCHAR(16) NOT NULL,
344-
value VARCHAR(128) NOT NULL,
344+
value VARCHAR(192) NOT NULL,
345345
synthetic VARCHAR(255) NOT NULL,
346346
userid BIGINT NOT NULL,
347347
resp VARCHAR(255),

0 commit comments

Comments
 (0)