Skip to content

Commit 601a6a0

Browse files
authored
[ Bugfix ] Satelite replication factor for shards information (#352)
1 parent 37c9d26 commit 601a6a0

File tree

9 files changed

+160
-15
lines changed

9 files changed

+160
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## [master](https://github.com/arangodb/go-driver/tree/master) (N/A)
44
- [V2] Add support for streaming the response body by the caller.
55
- [V2] Bugfix with escaping the URL path twice.
6+
- Bugfix for the satellites' collection shard info.
7+
- [V2] Support for satellites' collections.
68

79
## [1.2.1](https://github.com/arangodb/go-driver/tree/v1.2.1) (2021-09-21)
810
- Add support for fetching shards' info by the given collection name.

collection.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,3 +323,75 @@ type CollectionShards struct {
323323
// Available from 3.6 ArangoDB version.
324324
WriteConcern int `json:"writeConcern,omitempty"`
325325
}
326+
327+
type collectionShardsInternal struct {
328+
CollectionInfo
329+
330+
// CacheEnabled set cacheEnabled option in collection properties
331+
CacheEnabled bool `json:"cacheEnabled,omitempty"`
332+
333+
// Set to create a smart edge or vertex collection.
334+
// This requires ArangoDB Enterprise Edition.
335+
IsSmart bool `json:"isSmart,omitempty"`
336+
337+
KeyOptions struct {
338+
// Type specifies the type of the key generator. The currently available generators are traditional and autoincrement.
339+
Type KeyGeneratorType `json:"type,omitempty"`
340+
// AllowUserKeys; if set to true, then it is allowed to supply own key values in the _key attribute of a document.
341+
// If set to false, then the key generator is solely responsible for generating keys and supplying own key values in
342+
// the _key attribute of documents is considered an error.
343+
AllowUserKeys bool `json:"allowUserKeys,omitempty"`
344+
} `json:"keyOptions,omitempty"`
345+
346+
// Deprecated: use 'WriteConcern' instead.
347+
MinReplicationFactor int `json:"minReplicationFactor,omitempty"`
348+
349+
// NumberOfShards is the number of shards of the collection.
350+
// Only available in cluster setup.
351+
NumberOfShards int `json:"numberOfShards,omitempty"`
352+
353+
// This attribute specifies the name of the sharding strategy to use for the collection.
354+
// Can not be changed after creation.
355+
ShardingStrategy ShardingStrategy `json:"shardingStrategy,omitempty"`
356+
357+
// ShardKeys contains the names of document attributes that are used to determine the target shard for documents.
358+
// Only available in cluster setup.
359+
ShardKeys []string `json:"shardKeys,omitempty"`
360+
361+
// Shards is a list of shards that belong to the collection.
362+
// Each shard contains a list of DB servers where the first one is the leader and the rest are followers.
363+
Shards map[ShardID][]ServerID `json:"shards,omitempty"`
364+
365+
// StatusString represents status as a string.
366+
StatusString string `json:"statusString,omitempty"`
367+
368+
// ReplicationFactor contains how many copies of each shard are kept on different DBServers.
369+
// Only available in cluster setup.
370+
ReplicationFactor replicationFactor `json:"replicationFactor,omitempty"`
371+
372+
// WaitForSync; If true then creating, changing or removing documents will wait
373+
// until the data has been synchronized to disk.
374+
WaitForSync bool `json:"waitForSync,omitempty"`
375+
376+
// WriteConcern contains how many copies must be available before a collection can be written.
377+
// It is required that 1 <= WriteConcern <= ReplicationFactor.
378+
// Default is 1. Not available for satellite collections.
379+
// Available from 3.6 ArangoDB version.
380+
WriteConcern int `json:"writeConcern,omitempty"`
381+
}
382+
383+
func (p *CollectionShards) fromInternal(i collectionShardsInternal) {
384+
p.CollectionInfo = i.CollectionInfo
385+
p.CacheEnabled = i.CacheEnabled
386+
p.IsSmart = i.IsSmart
387+
p.KeyOptions = i.KeyOptions
388+
p.MinReplicationFactor = i.MinReplicationFactor
389+
p.NumberOfShards = i.NumberOfShards
390+
p.ShardingStrategy = i.ShardingStrategy
391+
p.ShardKeys = i.ShardKeys
392+
p.Shards = i.Shards
393+
p.StatusString = i.StatusString
394+
p.ReplicationFactor = int(i.ReplicationFactor)
395+
p.WaitForSync = i.WaitForSync
396+
p.WriteConcern = i.WriteConcern
397+
}

collection_impl.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,15 @@ func (c *collection) Shards(ctx context.Context, details bool) (CollectionShards
210210
return CollectionShards{}, WithStack(err)
211211
}
212212

213-
shards := CollectionShards{}
214-
if err := resp.ParseBody("", &shards); err != nil {
213+
shardsInternal := collectionShardsInternal{}
214+
if err := resp.ParseBody("", &shardsInternal); err != nil {
215215
return CollectionShards{}, WithStack(err)
216216
}
217217

218-
return shards, nil
218+
var shards CollectionShards
219+
shards.fromInternal(shardsInternal)
219220

221+
return shards, nil
220222
}
221223

222224
// Load the collection into memory.

test/collection_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,4 +1007,16 @@ func Test_CollectionShards(t *testing.T) {
10071007
assert.Equal(t, 2, shards.ReplicationFactor)
10081008
assert.Equal(t, false, shards.WaitForSync)
10091009
assert.Equal(t, 1, shards.WriteConcern)
1010+
1011+
t.Run("Satellite collection", func(t *testing.T) {
1012+
skipNoEnterprise(t)
1013+
col, err := db.CreateCollection(nil, "satellite", &driver.CreateCollectionOptions{
1014+
ReplicationFactor: driver.ReplicationFactorSatellite,
1015+
})
1016+
require.NoError(t, err)
1017+
1018+
shards, err := col.Shards(context.Background(), true)
1019+
require.NoError(t, err)
1020+
assert.Equal(t, driver.ReplicationFactorSatellite, shards.ReplicationFactor)
1021+
})
10101022
}

v2/arangodb/client_database.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ type CreateDatabaseOptions struct {
6666
// CreateDatabaseDefaultOptions contains options that change defaults for collections
6767
type CreateDatabaseDefaultOptions struct {
6868
// Default replication factor for collections in database
69-
ReplicationFactor int `json:"replicationFactor,omitempty"`
69+
ReplicationFactor ReplicationFactor `json:"replicationFactor,omitempty"`
7070
// Default write concern for collections in database
7171
WriteConcern int `json:"writeConcern,omitempty"`
7272
// Default sharding for collections in database

v2/arangodb/collection_opts.go

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,19 @@
2424
package arangodb
2525

2626
import (
27+
"encoding/json"
28+
"reflect"
2729
"time"
2830
)
2931

32+
type ReplicationFactor int
33+
34+
const (
35+
// ReplicationFactorSatellite represents a satellite collection's replication factor
36+
ReplicationFactorSatellite ReplicationFactor = -1
37+
replicationFactorSatelliteString string = "satellite"
38+
)
39+
3040
// CollectionInfo contains basic information about a collection.
3141
type CollectionInfo struct {
3242
// The identifier of the collection.
@@ -69,7 +79,7 @@ type CollectionExtendedInfo struct {
6979
ShardKeys []string `json:"shardKeys,omitempty"`
7080
// ReplicationFactor contains how many copies of each shard are kept on different DBServers.
7181
// Only available in cluster setup.
72-
ReplicationFactor int `json:"replicationFactor,omitempty"`
82+
ReplicationFactor ReplicationFactor `json:"replicationFactor,omitempty"`
7383
// WaitForSync; If true then creating, changing or removing documents will wait
7484
// until the data has been synchronized to disk.
7585
WaitForSync bool `json:"waitForSync,omitempty"`
@@ -104,11 +114,6 @@ type CollectionProperties struct {
104114
Schema *CollectionSchemaOptions `json:"schema,omitempty"`
105115
}
106116

107-
const (
108-
// ReplicationFactorSatellite represents a satellite collection's replication factor
109-
ReplicationFactorSatellite int = -1
110-
)
111-
112117
// IsSatellite returns true if the collection is a satellite collection
113118
func (p *CollectionProperties) IsSatellite() bool {
114119
return p.ReplicationFactor == ReplicationFactorSatellite
@@ -122,7 +127,7 @@ type SetCollectionPropertiesOptions struct {
122127
JournalSize int64 `json:"journalSize,omitempty"`
123128
// ReplicationFactor contains how many copies of each shard are kept on different DBServers.
124129
// Only available in cluster setup.
125-
ReplicationFactor int `json:"replicationFactor,omitempty"`
130+
ReplicationFactor ReplicationFactor `json:"replicationFactor,omitempty"`
126131
// Deprecated: use 'WriteConcern' instead
127132
MinReplicationFactor int `json:"minReplicationFactor,omitempty"`
128133
// WriteConcern contains how many copies must be available before a collection can be written.
@@ -234,3 +239,40 @@ type CollectionShards struct {
234239
// StatusString represents status as a string.
235240
StatusString string `json:"statusString,omitempty"`
236241
}
242+
243+
// MarshalJSON marshals InventoryCollectionParameters to arangodb json representation
244+
func (r ReplicationFactor) MarshalJSON() ([]byte, error) {
245+
var replicationFactor interface{}
246+
247+
if r == ReplicationFactorSatellite {
248+
replicationFactor = replicationFactorSatelliteString
249+
} else {
250+
replicationFactor = int(r)
251+
}
252+
253+
return json.Marshal(replicationFactor)
254+
}
255+
256+
// UnmarshalJSON marshals InventoryCollectionParameters to arangodb json representation
257+
func (r *ReplicationFactor) UnmarshalJSON(d []byte) error {
258+
var internal interface{}
259+
260+
if err := json.Unmarshal(d, &internal); err != nil {
261+
return err
262+
}
263+
264+
if i, ok := internal.(float64); ok {
265+
*r = ReplicationFactor(i)
266+
return nil
267+
} else if str, ok := internal.(string); ok {
268+
if ok && str == replicationFactorSatelliteString {
269+
*r = ReplicationFactor(ReplicationFactorSatellite)
270+
return nil
271+
}
272+
}
273+
274+
return &json.UnmarshalTypeError{
275+
Value: string(d),
276+
Type: reflect.TypeOf(r).Elem(),
277+
}
278+
}

v2/arangodb/database_collection_opts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type CreateCollectionOptions struct {
3232
// Replication between them is synchronous, that is, every write operation to the "leader" copy will be replicated to all "follower" replicas,
3333
// before the write operation is reported successful. If a server fails, this is detected automatically
3434
// and one of the servers holding copies take over, usually without an error being reported.
35-
ReplicationFactor int `json:"replicationFactor,omitempty"`
35+
ReplicationFactor ReplicationFactor `json:"replicationFactor,omitempty"`
3636
// Deprecated: use 'WriteConcern' instead
3737
MinReplicationFactor int `json:"minReplicationFactor,omitempty"`
3838
// WriteConcern contains how many copies must be available before a collection can be written.

v2/arangodb/database_opts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type DatabaseInfo struct {
3333
// If true then the database is the _system database.
3434
IsSystem bool `json:"isSystem,omitempty"`
3535
// Default replication factor for collections in database
36-
ReplicationFactor int `json:"replicationFactor,omitempty"`
36+
ReplicationFactor ReplicationFactor `json:"replicationFactor,omitempty"`
3737
// Default write concern for collections in database
3838
WriteConcern int `json:"writeConcern,omitempty"`
3939
// Default sharding for collections in database

v2/tests/database_collection_operations_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ import (
3939
func Test_CollectionShards(t *testing.T) {
4040
requireClusterMode(t)
4141

42+
rf := arangodb.ReplicationFactor(2)
4243
options := arangodb.CreateCollectionOptions{
43-
ReplicationFactor: 2,
44+
ReplicationFactor: rf,
4445
NumberOfShards: 2,
4546
}
4647

@@ -70,10 +71,24 @@ func Test_CollectionShards(t *testing.T) {
7071
leaders = append(leaders, dbServers[0])
7172
}
7273
assert.NotEqualf(t, leaders[0], leaders[1], "the leader shard can not be on the same server")
73-
assert.Equal(t, 2, shards.ReplicationFactor)
74+
assert.Equal(t, rf, shards.ReplicationFactor)
7475
assert.Equal(t, false, shards.WaitForSync)
7576
assert.Equal(t, 1, shards.WriteConcern)
7677
})
78+
79+
version, err := client.Version(context.Background())
80+
require.NoError(t, err)
81+
82+
if version.IsEnterprise() {
83+
optionsSatellite := arangodb.CreateCollectionOptions{
84+
ReplicationFactor: arangodb.ReplicationFactorSatellite,
85+
}
86+
WithCollection(t, db, &optionsSatellite, func(col arangodb.Collection) {
87+
shards, err := col.Shards(context.Background(), true)
88+
require.NoError(t, err)
89+
assert.Equal(t, arangodb.ReplicationFactorSatellite, shards.ReplicationFactor)
90+
})
91+
}
7792
})
7893
})
7994
}

0 commit comments

Comments
 (0)