Skip to content

Commit 63cef00

Browse files
authored
Feature/get shards info (#331)
* Get shards information * Add v2 test for getting collection shards * Create more reliable collection shards test
1 parent c680b93 commit 63cef00

13 files changed

+360
-30
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Change Log
22

33
## [master](https://github.com/arangodb/go-driver/tree/master) (N/A)
4+
- Add support for fetching shards' info by the given collection name.
45

56
## [1.2.0](https://github.com/arangodb/go-driver/tree/1.2.0) (2021-08-04)
67
- Add support for AQL, Pipeline, Stopwords, GeoJSON and GeoPoint Arango Search analyzers.

collection.go

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2021 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
2020
// Author Ewout Prangsma
21+
// Author Tomasz Mielech
2122
//
2223

2324
package driver
@@ -55,10 +56,13 @@ type Collection interface {
5556
// SetProperties changes properties of the collection.
5657
SetProperties(ctx context.Context, options SetCollectionPropertiesOptions) error
5758

59+
// Shards fetches shards information of the collection.
60+
Shards(ctx context.Context, details bool) (CollectionShards, error)
61+
5862
// Load the collection into memory.
5963
Load(ctx context.Context) error
6064

61-
// UnLoad the collection from memory.
65+
// Unload unloads the collection from memory.
6266
Unload(ctx context.Context) error
6367

6468
// Remove removes the entire collection.
@@ -262,3 +266,60 @@ type CollectionStatistics struct {
262266
} `json:"revisions"`
263267
} `json:"figures"`
264268
}
269+
270+
// CollectionShards contains shards information about a collection.
271+
type CollectionShards struct {
272+
CollectionInfo
273+
274+
// CacheEnabled set cacheEnabled option in collection properties
275+
CacheEnabled bool `json:"cacheEnabled,omitempty"`
276+
277+
// Set to create a smart edge or vertex collection.
278+
// This requires ArangoDB Enterprise Edition.
279+
IsSmart bool `json:"isSmart,omitempty"`
280+
281+
KeyOptions struct {
282+
// Type specifies the type of the key generator. The currently available generators are traditional and autoincrement.
283+
Type KeyGeneratorType `json:"type,omitempty"`
284+
// AllowUserKeys; if set to true, then it is allowed to supply own key values in the _key attribute of a document.
285+
// If set to false, then the key generator is solely responsible for generating keys and supplying own key values in
286+
// the _key attribute of documents is considered an error.
287+
AllowUserKeys bool `json:"allowUserKeys,omitempty"`
288+
} `json:"keyOptions,omitempty"`
289+
290+
// Deprecated: use 'WriteConcern' instead.
291+
MinReplicationFactor int `json:"minReplicationFactor,omitempty"`
292+
293+
// NumberOfShards is the number of shards of the collection.
294+
// Only available in cluster setup.
295+
NumberOfShards int `json:"numberOfShards,omitempty"`
296+
297+
// This attribute specifies the name of the sharding strategy to use for the collection.
298+
// Can not be changed after creation.
299+
ShardingStrategy ShardingStrategy `json:"shardingStrategy,omitempty"`
300+
301+
// ShardKeys contains the names of document attributes that are used to determine the target shard for documents.
302+
// Only available in cluster setup.
303+
ShardKeys []string `json:"shardKeys,omitempty"`
304+
305+
// Shards is a list of shards that belong to the collection.
306+
// Each shard contains a list of DB servers where the first one is the leader and the rest are followers.
307+
Shards map[ShardID][]ServerID `json:"shards,omitempty"`
308+
309+
// StatusString represents status as a string.
310+
StatusString string `json:"statusString,omitempty"`
311+
312+
// ReplicationFactor contains how many copies of each shard are kept on different DBServers.
313+
// Only available in cluster setup.
314+
ReplicationFactor int `json:"replicationFactor,omitempty"`
315+
316+
// WaitForSync; If true then creating, changing or removing documents will wait
317+
// until the data has been synchronized to disk.
318+
WaitForSync bool `json:"waitForSync,omitempty"`
319+
320+
// WriteConcern contains how many copies must be available before a collection can be written.
321+
// It is required that 1 <= WriteConcern <= ReplicationFactor.
322+
// Default is 1. Not available for satellite collections.
323+
// Available from 3.6 ArangoDB version.
324+
WriteConcern int `json:"writeConcern,omitempty"`
325+
}

collection_impl.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2021 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
2020
// Author Ewout Prangsma
21+
// Author Tomasz Mielech
2122
//
2223

2324
package driver
@@ -190,6 +191,34 @@ func (c *collection) SetProperties(ctx context.Context, options SetCollectionPro
190191
return nil
191192
}
192193

194+
// Shards fetches shards information of the collection.
195+
func (c *collection) Shards(ctx context.Context, details bool) (CollectionShards, error) {
196+
req, err := c.conn.NewRequest("GET", path.Join(c.relPath("collection"), "shards"))
197+
if err != nil {
198+
return CollectionShards{}, WithStack(err)
199+
}
200+
if details {
201+
req.SetQuery("details", "true")
202+
}
203+
204+
resp, err := c.conn.Do(ctx, req)
205+
if err != nil {
206+
return CollectionShards{}, WithStack(err)
207+
}
208+
209+
if err := resp.CheckStatus(200); err != nil {
210+
return CollectionShards{}, WithStack(err)
211+
}
212+
213+
shards := CollectionShards{}
214+
if err := resp.ParseBody("", &shards); err != nil {
215+
return CollectionShards{}, WithStack(err)
216+
}
217+
218+
return shards, nil
219+
220+
}
221+
193222
// Load the collection into memory.
194223
func (c *collection) Load(ctx context.Context) error {
195224
req, err := c.conn.NewRequest("PUT", path.Join(c.relPath("collection"), "load"))

edge_collection_impl.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2021 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
2020
// Author Ewout Prangsma
21+
// Author Tomasz Mielech
2122
//
2223

2324
package driver
@@ -126,6 +127,15 @@ func (c *edgeCollection) SetProperties(ctx context.Context, options SetCollectio
126127
return nil
127128
}
128129

130+
// Shards fetches shards information of the collection.
131+
func (c *edgeCollection) Shards(ctx context.Context, details bool) (CollectionShards, error) {
132+
result, err := c.rawCollection().Shards(ctx, details)
133+
if err != nil {
134+
return result, WithStack(err)
135+
}
136+
return result, nil
137+
}
138+
129139
// Load the collection into memory.
130140
func (c *edgeCollection) Load(ctx context.Context) error {
131141
if err := c.rawCollection().Load(ctx); err != nil {

test/collection_test.go

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2021 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
2020
// Author Ewout Prangsma
21+
// Author Tomasz Mielech
2122
//
2223

2324
package test
@@ -964,3 +965,46 @@ func TestCollectionWriteConcernSetPropInvalid(t *testing.T) {
964965
assert.Equalf(t, defaultWriteConcern, prop.WriteConcern, "MinReplicationFactor not updated, expected %d, found %d",
965966
minRepl, prop.WriteConcern)
966967
}
968+
969+
// Test_CollectionShards creates a collection and gets the shards' information.
970+
func Test_CollectionShards(t *testing.T) {
971+
if getTestMode() != testModeCluster {
972+
t.Skipf("Not a cluster mode")
973+
}
974+
975+
databaseName := getCallerFunctionName()
976+
c := createClientFromEnv(t, true)
977+
db := ensureDatabase(nil, c, databaseName, nil, t)
978+
name := "test_collection_set_properties"
979+
col, err := db.CreateCollection(nil, name, &driver.CreateCollectionOptions{
980+
ReplicationFactor: 2,
981+
NumberOfShards: 2,
982+
})
983+
require.NoError(t, err)
984+
985+
shards, err := col.Shards(context.Background(), true)
986+
require.NoError(t, err)
987+
assert.NotEmpty(t, shards.ID)
988+
assert.Equal(t, name, shards.Name)
989+
assert.NotEmpty(t, shards.Status)
990+
assert.Equal(t, driver.CollectionTypeDocument, shards.Type)
991+
assert.Equal(t, false, shards.IsSystem)
992+
assert.NotEmpty(t, shards.GloballyUniqueId)
993+
assert.Equal(t, false, shards.CacheEnabled)
994+
assert.Equal(t, false, shards.IsSmart)
995+
assert.Equal(t, driver.KeyGeneratorTraditional, shards.KeyOptions.Type)
996+
assert.Equal(t, true, shards.KeyOptions.AllowUserKeys)
997+
assert.Equal(t, 2, shards.NumberOfShards)
998+
assert.Equal(t, driver.ShardingStrategyHash, shards.ShardingStrategy)
999+
assert.Equal(t, []string{"_key"}, shards.ShardKeys)
1000+
require.Len(t, shards.Shards, 2, "expected 2 shards")
1001+
var leaders []driver.ServerID
1002+
for _, dbServers := range shards.Shards {
1003+
require.Lenf(t, dbServers, 2, "expected 2 DB servers for the shard")
1004+
leaders = append(leaders, dbServers[0])
1005+
}
1006+
assert.NotEqualf(t, leaders[0], leaders[1], "the leader shard can not be on the same server")
1007+
assert.Equal(t, 2, shards.ReplicationFactor)
1008+
assert.Equal(t, false, shards.WaitForSync)
1009+
assert.Equal(t, 1, shards.WriteConcern)
1010+
}

test/util.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2021 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
2020
// Author Ewout Prangsma
21+
// Author Tomasz Mielech
2122
//
2223

2324
package test
@@ -28,13 +29,14 @@ import (
2829
"encoding/json"
2930
"fmt"
3031
"os"
32+
"runtime"
3133
"strconv"
3234
"strings"
3335
"testing"
3436
"time"
3537

38+
"github.com/dchest/uniuri"
3639
"github.com/google/uuid"
37-
3840
"github.com/stretchr/testify/require"
3941

4042
driver "github.com/arangodb/go-driver"
@@ -212,3 +214,18 @@ func min(max int, ints ...int) int {
212214

213215
return z
214216
}
217+
218+
// getCallerFunctionName returns the name of the function of the caller.
219+
func getCallerFunctionName() string {
220+
programCounters := make([]uintptr, 10)
221+
// skip this function and 'runtime.Callers' function
222+
runtime.Callers(2, programCounters)
223+
functionPackage := runtime.FuncForPC(programCounters[0])
224+
225+
function := strings.Split(functionPackage.Name(), ".")
226+
if len(function) > 1 {
227+
return function[len(function)-1] + "_" + uniuri.NewLen(6)
228+
}
229+
230+
return function[0] + "_" + uniuri.NewLen(6)
231+
}

v2/arangodb/collection.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2020-2021 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
2020
// Author Adam Janikowski
21+
// Author Tomasz Mielech
2122
//
2223

2324
package arangodb
@@ -28,6 +29,9 @@ type Collection interface {
2829
Name() string
2930
Database() Database
3031

32+
// Shards fetches shards information of the collection.
33+
Shards(ctx context.Context, details bool) (CollectionShards, error)
34+
3135
// Remove removes the entire collection.
3236
// If the collection does not exist, a NotFoundError is returned.
3337
Remove(ctx context.Context) error

v2/arangodb/collection_impl.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2020-2021 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
2020
// Author Adam Janikowski
21+
// Author Tomasz Mielech
2122
//
2223

2324
package arangodb
@@ -26,8 +27,9 @@ import (
2627
"context"
2728
"net/http"
2829

29-
"github.com/arangodb/go-driver/v2/arangodb/shared"
30+
"github.com/pkg/errors"
3031

32+
"github.com/arangodb/go-driver/v2/arangodb/shared"
3133
"github.com/arangodb/go-driver/v2/connection"
3234
)
3335

@@ -104,3 +106,24 @@ func (c collection) connection() connection.Connection {
104106
func (c collection) url(api string, parts ...string) string {
105107
return c.db.url(append([]string{"_api", api, c.name}, parts...)...)
106108
}
109+
110+
// Shards fetches shards information of the collection.
111+
func (c *collection) Shards(ctx context.Context, details bool) (CollectionShards, error) {
112+
var body struct {
113+
shared.ResponseStruct `json:",inline"`
114+
CollectionShards `json:",inline"`
115+
}
116+
117+
resp, err := connection.CallGet(ctx, c.connection(), c.url("collection", "shards"), &body,
118+
connection.WithQuery("details", "true"))
119+
if err != nil {
120+
return CollectionShards{}, errors.WithStack(err)
121+
}
122+
123+
switch code := resp.Code(); code {
124+
case http.StatusOK:
125+
return body.CollectionShards, nil
126+
default:
127+
return CollectionShards{}, body.AsArangoErrorWithCode(code)
128+
}
129+
}

0 commit comments

Comments
 (0)