Skip to content

Commit 8d0d862

Browse files
committed
box: add replication information
1 parent 7eae014 commit 8d0d862

File tree

5 files changed

+187
-0
lines changed

5 files changed

+187
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
1010

1111
### Added
1212

13+
- Extend box with replication information (#427).
14+
1315
### Changed
1416

1517
### Fixed

box/info.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,57 @@ type Info struct {
2626
Status string `msgpack:"status"`
2727
// LSN - Log sequence number of the instance.
2828
LSN uint64 `msgpack:"lsn"`
29+
// Replication - replication status
30+
Replication map[int]Replication `msgpack:"replication,omitempty"`
31+
}
32+
33+
// Replication section of box.info() is a table with statistics for all instances
34+
// in the replica set that the current instance belongs to.
35+
type Replication struct {
36+
// ID is a short numeric identifier of instance n within the replica set
37+
ID int `msgpack:"id"`
38+
// UUID - Unique identifier of the instance.
39+
UUID string `msgpack:"uuid"`
40+
// LSN - Log sequence number of the instance.
41+
LSN uint64 `msgpack:"lsn"`
42+
// Upstream - information about upstream.
43+
Upstream Upstream `msgpack:"upstream,omitempty"`
44+
// Downstream - information about downstream.
45+
Downstream Downstream `msgpack:"downstream,omitempty"`
46+
}
47+
48+
// Upstream information.
49+
type Upstream struct {
50+
// Status is replication status of the connection with the instance.
51+
Status string `msgpack:"status"`
52+
// Idle is the time (in seconds) since the last event was received.
53+
Idle float64 `msgpack:"idle"`
54+
// Contains instance n’s URI.
55+
Peer string `msgpack:"peer"`
56+
// Lag is the time difference between the local time of instance n, recorded when the event was received,
57+
// and the local time at another master recorded when the event was written to the write-ahead log on that master.
58+
Lag float64 `msgpack:"lag"`
59+
// Message contains an error message in case of a degraded state; otherwise, it is nil.
60+
Message string `msgpack:"message,omitempty"`
61+
// SystemMessage contains an error message in case of a degraded state; otherwise, it is nil.
62+
SystemMessage string `msgpack:"system_message,omitempty"`
63+
}
64+
65+
// Downstream information.
66+
type Downstream struct {
67+
// Status is replication status of the connection with the instance.
68+
Status string `msgpack:"status"`
69+
// Idle is the time (in seconds) since the last event was received.
70+
Idle float64 `msgpack:"idle"`
71+
// Contains the vector clock, which is a table of ‘id, lsn’ pairs.
72+
VClock map[int]uint64 `msgpack:"vclock"`
73+
// Lag is the time difference between the local time of instance n, recorded when the event was received,
74+
// and the local time at another master recorded when the event was written to the write-ahead log on that master.
75+
Lag float64 `msgpack:"lag"`
76+
// Message contains an error message in case of a degraded state; otherwise, it is nil.
77+
Message string `msgpack:"message,omitempty"`
78+
// SystemMessage contains an error message in case of a degraded state; otherwise, it is nil.
79+
SystemMessage string `msgpack:"system_message,omitempty"`
2980
}
3081

3182
// InfoResponse represents the response structure

box/info_test.go

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package box
2+
3+
import (
4+
"github.com/stretchr/testify/require"
5+
"github.com/vmihailenco/msgpack/v5"
6+
"testing"
7+
)
8+
9+
func TestInfoRequest(t *testing.T) {
10+
id := 1
11+
cases := []struct {
12+
Name string
13+
Struct Info
14+
Data map[string]interface{}
15+
}{
16+
{
17+
Name: "Case: base info struct",
18+
Struct: Info{
19+
Version: "2.11.4-0-g8cebbf2cad",
20+
ID: &id,
21+
RO: false,
22+
UUID: "69360e9b-4641-4ec3-ab51-297f46749849",
23+
PID: 1,
24+
Status: "running",
25+
LSN: 8,
26+
},
27+
Data: map[string]interface{}{
28+
"version": "2.11.4-0-g8cebbf2cad",
29+
"id": 1,
30+
"ro": false,
31+
"uuid": "69360e9b-4641-4ec3-ab51-297f46749849",
32+
"pid": 1,
33+
"status": "running",
34+
"lsn": 8,
35+
},
36+
},
37+
{
38+
Name: "Case: info struct with replication",
39+
Struct: Info{
40+
Version: "2.11.4-0-g8cebbf2cad",
41+
ID: &id,
42+
RO: false,
43+
UUID: "69360e9b-4641-4ec3-ab51-297f46749849",
44+
PID: 1,
45+
Status: "running",
46+
LSN: 8,
47+
Replication: map[int]Replication{
48+
1: {
49+
ID: 1,
50+
UUID: "69360e9b-4641-4ec3-ab51-297f46749849",
51+
LSN: 8,
52+
},
53+
2: {
54+
ID: 2,
55+
UUID: "75f5f5aa-89f0-4d95-b5a9-96a0eaa0ce36",
56+
LSN: 0,
57+
Upstream: Upstream{
58+
Status: "follow",
59+
Idle: 2.4564633660484,
60+
Peer: "other.tarantool:3301",
61+
Lag: 0.00011920928955078,
62+
Message: "'getaddrinfo: Name or service not known: Input/output error'",
63+
SystemMessage: "Input/output error",
64+
},
65+
Downstream: Downstream{
66+
Status: "follow",
67+
Idle: 2.8306158290943,
68+
VClock: map[int]uint64{1: 8},
69+
Lag: 0,
70+
Message: "'unexpected EOF when reading from socket'",
71+
SystemMessage: "Broken pipe",
72+
},
73+
},
74+
},
75+
},
76+
Data: map[string]interface{}{
77+
"version": "2.11.4-0-g8cebbf2cad",
78+
"id": 1,
79+
"ro": false,
80+
"uuid": "69360e9b-4641-4ec3-ab51-297f46749849",
81+
"pid": 1,
82+
"status": "running",
83+
"lsn": 8,
84+
"replication": map[interface{}]interface{}{
85+
1: map[string]interface{}{
86+
"id": 1,
87+
"uuid": "69360e9b-4641-4ec3-ab51-297f46749849",
88+
"lsn": 8,
89+
},
90+
2: map[string]interface{}{
91+
"id": 2,
92+
"uuid": "75f5f5aa-89f0-4d95-b5a9-96a0eaa0ce36",
93+
"lsn": 0,
94+
"upstream": map[string]interface{}{
95+
"status": "follow",
96+
"idle": 2.4564633660484,
97+
"peer": "other.tarantool:3301",
98+
"lag": 0.00011920928955078,
99+
"message": "'getaddrinfo: Name or service not known: Input/output error'",
100+
"system_message": "Input/output error",
101+
},
102+
"downstream": map[string]interface{}{
103+
"status": "follow",
104+
"idle": 2.8306158290943,
105+
"vclock": map[interface{}]interface{}{1: 8},
106+
"lag": 0,
107+
"message": "'unexpected EOF when reading from socket'",
108+
"system_message": "Broken pipe",
109+
},
110+
},
111+
},
112+
},
113+
},
114+
}
115+
for _, tc := range cases {
116+
data, err := msgpack.Marshal(tc.Data)
117+
require.NoError(t, err, tc.Name)
118+
119+
var result Info
120+
err = msgpack.Unmarshal(data, &result)
121+
require.NoError(t, err, tc.Name)
122+
123+
require.Equal(t, tc.Struct, result)
124+
}
125+
}

box/tarantool_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ func validateInfo(t testing.TB, info box.Info) {
3131
require.NotEmpty(t, info.Version)
3232
// Check that pid parsed correctly.
3333
require.NotEqual(t, info.PID, 0)
34+
35+
// Check replication is parsed correctly.
36+
require.NotEmpty(t, info.Replication)
37+
38+
// Check one replica uuid is equal system uuid.
39+
require.Equal(t, info.UUID, info.Replication[1].UUID)
3440
}
3541

3642
func TestBox_Sugar_Info(t *testing.T) {

box/testdata/config.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ box.schema.user.grant('test', 'execute', 'universe', nil, { if_not_exists = true
1010
-- Set listen only when every other thing is configured.
1111
box.cfg{
1212
listen = os.getenv("TEST_TNT_LISTEN"),
13+
replication = {
14+
os.getenv("TEST_TNT_LISTEN"),
15+
};
1316
}

0 commit comments

Comments
 (0)