Skip to content

Commit 92fe8b5

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` + `OverrideSchema` in pair. Closes #7
1 parent 6225ec4 commit 92fe8b5

8 files changed

+86
-27
lines changed

CHANGELOG.md

+2
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 used by the connection (#7)
2930

3031
### Changed
3132

@@ -70,6 +71,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
7071
- UUID_extId (#158)
7172
- IPROTO constants (#158)
7273
- Code() method from the Request interface (#158)
74+
- `Schema` field from the `Connection` struct (#7)
7375

7476
### Fixed
7577

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ 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(*Connection)` function was added to get the actual connection
255+
schema on demand.
256+
251257
#### Protocol changes
252258

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

connection.go

+11-4
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.OverrideSchema(schema)
445445
}
446446

447447
return conn, err
@@ -1305,12 +1305,19 @@ func (conn *Connection) ConfiguredTimeout() time.Duration {
13051305
// OverrideSchema sets Schema for the connection.
13061306
func (conn *Connection) OverrideSchema(s *Schema) {
13071307
if s != nil {
1308+
spaceAndIndexNamesSupported :=
1309+
isFeatureInSlice(iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES,
1310+
conn.serverProtocolInfo.Features)
1311+
13081312
conn.mutex.Lock()
13091313
defer conn.mutex.Unlock()
13101314
conn.lockShards()
13111315
defer conn.unlockShards()
13121316

1313-
conn.Schema = s
1317+
conn.schemaResolver = &loadedSchemaResolver{
1318+
Schema: s,
1319+
SpaceAndIndexNamesSupported: spaceAndIndexNamesSupported,
1320+
}
13141321
}
13151322
}
13161323

example_test.go

+22-2
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 ExampleSchema_update() {
1088+
conn := exampleConnect(opts)
1089+
defer conn.Close()
1090+
1091+
// Get the actual schema, used by the connection.
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.OverrideSchema(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
}

request_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ func (r *ValidSchemeResolver) NamesUseSupported() bool {
7878
return r.nameUseSupported
7979
}
8080

81+
func (r *ValidSchemeResolver) GetSchema() *Schema {
82+
return nil
83+
}
84+
8185
var resolver ValidSchemeResolver
8286

8387
func assertBodyCall(t testing.TB, requests []Request, errorMsg string) {

schema.go

+16-19
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
)
@@ -52,6 +51,8 @@ type SchemaResolver interface {
5251
// IDs, is supported. It must return true if
5352
// iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES is supported.
5453
NamesUseSupported() bool
54+
// GetSchema returns inner Schema.
55+
GetSchema() *Schema
5556
}
5657

5758
// Schema contains information about spaces and indexes.
@@ -340,16 +341,16 @@ func (indexField *IndexField) DecodeMsgpack(d *msgpack.Decoder) error {
340341
return errors.New("unexpected schema format (index fields)")
341342
}
342343

343-
func (conn *Connection) loadSchema() (err error) {
344+
func GetSchema(conn *Connection) (*Schema, error) {
344345
schema := new(Schema)
345346
schema.SpacesById = make(map[uint32]*Space)
346347
schema.Spaces = make(map[string]*Space)
347348

348349
// Reload spaces.
349350
var spaces []*Space
350-
err = conn.SelectTyped(vspaceSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &spaces)
351+
err := conn.SelectTyped(vspaceSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &spaces)
351352
if err != nil {
352-
return err
353+
return nil, err
353354
}
354355
for _, space := range spaces {
355356
schema.SpacesById[space.Id] = space
@@ -360,31 +361,19 @@ func (conn *Connection) loadSchema() (err error) {
360361
var indexes []*Index
361362
err = conn.SelectTyped(vindexSpId, 0, 0, maxSchemas, IterAll, []interface{}{}, &indexes)
362363
if err != nil {
363-
return err
364+
return nil, err
364365
}
365366
for _, index := range indexes {
366367
spaceId := index.SpaceId
367368
if _, ok := schema.SpacesById[spaceId]; ok {
368369
schema.SpacesById[spaceId].IndexesById[index.Id] = index
369370
schema.SpacesById[spaceId].Indexes[index.Name] = index
370371
} else {
371-
return errors.New("concurrent schema update")
372+
return nil, errors.New("concurrent schema update")
372373
}
373374
}
374375

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
376+
return schema, nil
388377
}
389378

390379
// resolveSpaceNumber tries to resolve a space number.
@@ -502,6 +491,10 @@ func (r *loadedSchemaResolver) NamesUseSupported() bool {
502491
return r.SpaceAndIndexNamesSupported
503492
}
504493

494+
func (r *loadedSchemaResolver) GetSchema() *Schema {
495+
return r.Schema
496+
}
497+
505498
type noSchemaResolver struct {
506499
// SpaceAndIndexNamesSupported shows if a current Tarantool version supports
507500
// iproto.IPROTO_FEATURE_SPACE_AND_INDEX_NAMES.
@@ -527,3 +520,7 @@ func (*noSchemaResolver) ResolveIndex(i interface{}, spaceNo uint32) (uint32, er
527520
func (r *noSchemaResolver) NamesUseSupported() bool {
528521
return r.SpaceAndIndexNamesSupported
529522
}
523+
524+
func (r *noSchemaResolver) GetSchema() *Schema {
525+
return nil
526+
}

settings/request_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ func (r *ValidSchemeResolver) NamesUseSupported() bool {
2828
return false
2929
}
3030

31+
func (r *ValidSchemeResolver) GetSchema() *tarantool.Schema {
32+
return nil
33+
}
34+
3135
var resolver ValidSchemeResolver
3236

3337
func TestRequestsAPI(t *testing.T) {

tarantool_test.go

+21-2
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)