Skip to content

Commit 66c5253

Browse files
committed
api: write a connection schema getter
Write a helper function to load the actual schema for the user. Previously we stored actual schema in a private `schemaResolver` field and `Schema` field was used only to get a current schema. But now because of the new function, we don't need to store the `Schema` as a different field. So `Schema` was also removed. To update the schema, used needs to use `GetSchema` + `SetSchema` in pair. `SetSchema` is a renamed `OverrideSchema`. Closes #7
1 parent 6225ec4 commit 66c5253

File tree

6 files changed

+77
-35
lines changed

6 files changed

+77
-35
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
2626
- Support `IPROTO_FEATURE_SPACE_AND_INDEX_NAMES` for Tarantool
2727
version >= 3.0.0-alpha1 (#338). It allows to use space and index names
2828
in requests instead of their IDs.
29+
- `GetSchema` function to get the actual schema (#7)
2930

3031
### Changed
3132

@@ -51,6 +52,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
5152
instead of `crud.OptUint` (#342)
5253
- Change all `Upsert` and `Update` requests to accept `*tarantool.Operations`
5354
as `ops` parameters instead of `interface{}` (#348)
55+
- Change `OverrideSchema()` to `SetSchema()` (#7)
5456

5557
### Deprecated
5658

@@ -70,6 +72,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
7072
- UUID_extId (#158)
7173
- IPROTO constants (#158)
7274
- Code() method from the Request interface (#158)
75+
- `Schema` field from the `Connection` struct (#7)
7376

7477
### Fixed
7578

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,13 @@ now does not attempt to reconnect and tries to establish a connection only once.
248248
Function might be canceled via context. Context accepted as first argument,
249249
and user may cancel it in process.
250250

251+
#### Connection schema
252+
253+
* Removed `Schema` field from the `Connection` struct. Instead, new
254+
`GetSchema(Connector)` function was added to get the actual connection
255+
schema on demand.
256+
* `OverrideSchema` method renamed to the `SetSchema`.
257+
251258
#### Protocol changes
252259

253260
* `iproto.Feature` type used instead of `ProtocolFeature`.

connection.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,6 @@ type Connection struct {
160160
c Conn
161161
mutex sync.Mutex
162162
cond *sync.Cond
163-
// Schema contains schema loaded on connection.
164-
Schema *Schema
165163
// schemaResolver contains a SchemaResolver implementation.
166164
schemaResolver SchemaResolver
167165
// requestId contains the last request ID for requests with nil context.
@@ -436,12 +434,14 @@ func Connect(ctx context.Context, addr string, opts Opts) (conn *Connection, err
436434

437435
// TODO: reload schema after reconnect.
438436
if !conn.opts.SkipSchema {
439-
if err = conn.loadSchema(); err != nil {
437+
schema, err := GetSchema(conn)
438+
if err != nil {
440439
conn.mutex.Lock()
441440
defer conn.mutex.Unlock()
442441
conn.closeConnection(err, true)
443442
return nil, err
444443
}
444+
conn.SetSchema(schema)
445445
}
446446

447447
return conn, err
@@ -1302,15 +1302,20 @@ func (conn *Connection) ConfiguredTimeout() time.Duration {
13021302
return conn.opts.Timeout
13031303
}
13041304

1305-
// OverrideSchema sets Schema for the connection.
1306-
func (conn *Connection) OverrideSchema(s *Schema) {
1307-
if s != nil {
1308-
conn.mutex.Lock()
1309-
defer conn.mutex.Unlock()
1310-
conn.lockShards()
1311-
defer conn.unlockShards()
1305+
// SetSchema sets Schema for the connection.
1306+
func (conn *Connection) SetSchema(s Schema) {
1307+
spaceAndIndexNamesSupported :=
1308+
isFeatureInSlice(iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES,
1309+
conn.serverProtocolInfo.Features)
13121310

1313-
conn.Schema = s
1311+
conn.mutex.Lock()
1312+
defer conn.mutex.Unlock()
1313+
conn.lockShards()
1314+
defer conn.unlockShards()
1315+
1316+
conn.schemaResolver = &loadedSchemaResolver{
1317+
Schema: &s,
1318+
SpaceAndIndexNamesSupported: spaceAndIndexNamesSupported,
13141319
}
13151320
}
13161321

example_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,10 @@ func ExampleSchema() {
10631063
conn := exampleConnect(opts)
10641064
defer conn.Close()
10651065

1066-
schema := conn.Schema
1066+
schema, err := tarantool.GetSchema(conn)
1067+
if err != nil {
1068+
fmt.Printf("unexpected error: %s\n", err.Error())
1069+
}
10671070
if schema.SpacesById == nil {
10681071
fmt.Println("schema.SpacesById is nil")
10691072
}
@@ -1080,13 +1083,30 @@ func ExampleSchema() {
10801083
// Space 2 ID 616 schematest
10811084
}
10821085

1086+
// Example demonstrates how to update the connection schema.
1087+
func ExampleConnection_SetSchema() {
1088+
conn := exampleConnect(opts)
1089+
defer conn.Close()
1090+
1091+
// Get the actual schema.
1092+
schema, err := tarantool.GetSchema(conn)
1093+
if err != nil {
1094+
fmt.Printf("unexpected error: %s\n", err.Error())
1095+
}
1096+
// Update the current schema to match the actual one.
1097+
conn.SetSchema(schema)
1098+
}
1099+
10831100
// Example demonstrates how to retrieve information with space schema.
10841101
func ExampleSpace() {
10851102
conn := exampleConnect(opts)
10861103
defer conn.Close()
10871104

10881105
// Save Schema to a local variable to avoid races
1089-
schema := conn.Schema
1106+
schema, err := tarantool.GetSchema(conn)
1107+
if err != nil {
1108+
fmt.Printf("unexpected error: %s\n", err.Error())
1109+
}
10901110
if schema.SpacesById == nil {
10911111
fmt.Println("schema.SpacesById is nil")
10921112
}

schema.go

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"errors"
55
"fmt"
66

7-
"github.com/tarantool/go-iproto"
87
"github.com/vmihailenco/msgpack/v5"
98
"github.com/vmihailenco/msgpack/v5/msgpcode"
109
)
@@ -340,16 +339,17 @@ func (indexField *IndexField) DecodeMsgpack(d *msgpack.Decoder) error {
340339
return errors.New("unexpected schema format (index fields)")
341340
}
342341

343-
func (conn *Connection) loadSchema() (err error) {
344-
schema := new(Schema)
342+
// GetSchema returns the actual schema for the connection.
343+
func GetSchema(conn Connector) (Schema, error) {
344+
schema := Schema{}
345345
schema.SpacesById = make(map[uint32]*Space)
346346
schema.Spaces = make(map[string]*Space)
347347

348348
// Reload spaces.
349349
var spaces []*Space
350-
err = conn.SelectTyped(vspaceSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &spaces)
350+
err := conn.SelectTyped(vspaceSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &spaces)
351351
if err != nil {
352-
return err
352+
return Schema{}, err
353353
}
354354
for _, space := range spaces {
355355
schema.SpacesById[space.Id] = space
@@ -360,31 +360,19 @@ func (conn *Connection) loadSchema() (err error) {
360360
var indexes []*Index
361361
err = conn.SelectTyped(vindexSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &indexes)
362362
if err != nil {
363-
return err
363+
return Schema{}, err
364364
}
365365
for _, index := range indexes {
366366
spaceId := index.SpaceId
367367
if _, ok := schema.SpacesById[spaceId]; ok {
368368
schema.SpacesById[spaceId].IndexesById[index.Id] = index
369369
schema.SpacesById[spaceId].Indexes[index.Name] = index
370370
} else {
371-
return errors.New("concurrent schema update")
371+
return Schema{}, errors.New("concurrent schema update")
372372
}
373373
}
374374

375-
spaceAndIndexNamesSupported :=
376-
isFeatureInSlice(iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES,
377-
conn.serverProtocolInfo.Features)
378-
379-
conn.lockShards()
380-
conn.Schema = schema
381-
conn.schemaResolver = &loadedSchemaResolver{
382-
Schema: schema,
383-
SpaceAndIndexNamesSupported: spaceAndIndexNamesSupported,
384-
}
385-
conn.unlockShards()
386-
387-
return nil
375+
return schema, nil
388376
}
389377

390378
// resolveSpaceNumber tries to resolve a space number.

tarantool_test.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,19 @@ func TestConnection_DoWithStrangerConn(t *testing.T) {
18511851
}
18521852
}
18531853

1854+
func TestGetSchema(t *testing.T) {
1855+
conn := test_helpers.ConnectWithValidation(t, server, opts)
1856+
defer conn.Close()
1857+
1858+
s, err := GetSchema(conn)
1859+
if err != nil {
1860+
t.Errorf("unexpected error: %s", err.Error())
1861+
}
1862+
if s.Version != 0 || s.Spaces[spaceName].Id != spaceNo {
1863+
t.Errorf("GetSchema() returns incorrect schema")
1864+
}
1865+
}
1866+
18541867
func TestNewPreparedFromResponse(t *testing.T) {
18551868
var (
18561869
ErrNilResponsePassed = fmt.Errorf("passed nil response")
@@ -1882,7 +1895,10 @@ func TestSchema(t *testing.T) {
18821895
defer conn.Close()
18831896

18841897
// Schema
1885-
schema := conn.Schema
1898+
schema, err := GetSchema(conn)
1899+
if err != nil {
1900+
t.Errorf("unexpected error: %s", err.Error())
1901+
}
18861902
if schema.SpacesById == nil {
18871903
t.Errorf("schema.SpacesById is nil")
18881904
}
@@ -2028,7 +2044,10 @@ func TestSchema_IsNullable(t *testing.T) {
20282044
conn := test_helpers.ConnectWithValidation(t, server, opts)
20292045
defer conn.Close()
20302046

2031-
schema := conn.Schema
2047+
schema, err := GetSchema(conn)
2048+
if err != nil {
2049+
t.Errorf("unexpected error: %s", err.Error())
2050+
}
20322051
if schema.Spaces == nil {
20332052
t.Errorf("schema.Spaces is nil")
20342053
}

0 commit comments

Comments
 (0)