-
Notifications
You must be signed in to change notification settings - Fork 543
Added new output binding for Cosmos Graph DB - Gremlin #885
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b822ee1
5200a95
a400ae1
3cda4a6
a012243
8b9f1f2
265e796
9bd6b3b
3fa4e13
e34578d
ef97191
c986c74
3987e4d
6043763
55a4ece
3d250e8
0216684
606a964
305eb25
83e9716
b366e1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| // ------------------------------------------------------------ | ||
| // Copyright (c) Microsoft Corporation and Dapr Contributors. | ||
| // Licensed under the MIT License. | ||
| // ------------------------------------------------------------ | ||
|
|
||
| package cosmosgraphdb | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "errors" | ||
| "fmt" | ||
| "time" | ||
|
|
||
| "github.com/dapr/components-contrib/bindings" | ||
| "github.com/dapr/kit/logger" | ||
| gremcos "github.com/supplyon/gremcos" | ||
| ) | ||
|
|
||
| const ( | ||
| queryOperation bindings.OperationKind = "query" | ||
|
|
||
| // keys from request's Data | ||
| commandGremlinKey = "gremlin" | ||
|
|
||
| // keys from response's Data | ||
| respGremlinKey = "gremlin" | ||
| respOpKey = "operation" | ||
| respStartTimeKey = "start-time" | ||
| respEndTimeKey = "end-time" | ||
| respDurationKey = "duration" | ||
| ) | ||
|
|
||
| // CosmosGraphDB allows performing state operations on collections | ||
| type CosmosGraphDB struct { | ||
| metadata *cosmosGraphDBCredentials | ||
| client *gremcos.Cosmos | ||
| logger logger.Logger | ||
| } | ||
|
|
||
| type cosmosGraphDBCredentials struct { | ||
| URL string `json:"url"` | ||
| MasterKey string `json:"masterKey"` | ||
| Username string `json:"username"` | ||
| } | ||
|
|
||
| // NewCosmosGraphDB returns a new CosmosGraphDB instance | ||
| func NewCosmosGraphDB(logger logger.Logger) *CosmosGraphDB { | ||
| return &CosmosGraphDB{logger: logger} | ||
| } | ||
|
|
||
| // Init performs CosmosDB connection parsing and connecting | ||
| func (c *CosmosGraphDB) Init(metadata bindings.Metadata) error { | ||
| c.logger.Debug("Initializing Cosmos Graph DB binding") | ||
|
|
||
| m, err := c.parseMetadata(metadata) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| c.metadata = m | ||
| client, err := gremcos.New(c.metadata.URL, | ||
| gremcos.WithAuth(c.metadata.Username, c.metadata.MasterKey), | ||
| ) | ||
| if err != nil { | ||
| return errors.New("CosmosGraphDB Error: failed to create the Cosmos Graph DB connector") | ||
| } | ||
|
|
||
| c.client = client | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func (c *CosmosGraphDB) parseMetadata(metadata bindings.Metadata) (*cosmosGraphDBCredentials, error) { | ||
| b, err := json.Marshal(metadata.Properties) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| var creds cosmosGraphDBCredentials | ||
| err = json.Unmarshal(b, &creds) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return &creds, nil | ||
| } | ||
|
|
||
| func (c *CosmosGraphDB) Operations() []bindings.OperationKind { | ||
| return []bindings.OperationKind{queryOperation} | ||
| } | ||
|
|
||
| func (c *CosmosGraphDB) Invoke(req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) { | ||
| var jsonPoint map[string]interface{} | ||
| err := json.Unmarshal(req.Data, &jsonPoint) | ||
| if err != nil { | ||
| return nil, errors.New("CosmosGraphDB Error: Cannot convert request data") | ||
| } | ||
|
|
||
| gq := fmt.Sprintf("%s", jsonPoint[commandGremlinKey]) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: It might more sense to unmarshal into an inline struct instead of type gremlinData struct {
Gremlin string `json:"gremlin"` // Note sure if this is always a string, use `interface{}` otherwise.
}
var jsonPoint gremlinDataAlso, using gq := fmt.Sprintf("%v", jsonPoint[commandGremlinKey]) |
||
|
|
||
| if gq == "" { | ||
| return nil, errors.New("CosmosGraphDB Error: missing data - gremlin query not set") | ||
| } | ||
| startTime := time.Now().UTC() | ||
| resp := &bindings.InvokeResponse{ | ||
| Metadata: map[string]string{ | ||
| respOpKey: string(req.Operation), | ||
| respGremlinKey: gq, | ||
| respStartTimeKey: startTime.Format(time.RFC3339Nano), | ||
| }, | ||
| } | ||
| d, err := c.client.Execute(gq) | ||
| if err != nil { | ||
| return nil, errors.New("CosmosGraphDB Error:error excuting gremlin") | ||
| } | ||
| if len(d) > 0 { | ||
| resp.Data = d[0].Result.Data | ||
| } | ||
| endTime := time.Now().UTC() | ||
| resp.Metadata[respEndTimeKey] = endTime.Format(time.RFC3339Nano) | ||
| resp.Metadata[respDurationKey] = endTime.Sub(startTime).String() | ||
|
|
||
| return resp, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // ------------------------------------------------------------ | ||
| // Copyright (c) Microsoft Corporation and Dapr Contributors. | ||
| // Licensed under the MIT License. | ||
| // ------------------------------------------------------------ | ||
|
|
||
| package cosmosgraphdb | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/dapr/components-contrib/bindings" | ||
| "github.com/dapr/kit/logger" | ||
| "github.com/stretchr/testify/assert" | ||
| ) | ||
|
|
||
| func TestParseMetadata(t *testing.T) { | ||
| m := bindings.Metadata{} | ||
| m.Properties = map[string]string{"Url": "a", "masterKey": "a", "username": "a"} | ||
yaron2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| cosmosgraphdb := CosmosGraphDB{logger: logger.NewLogger("test")} | ||
| im, err := cosmosgraphdb.parseMetadata(m) | ||
| assert.Nil(t, err) | ||
| assert.Equal(t, "a", im.URL) | ||
| assert.Equal(t, "a", im.MasterKey) | ||
| assert.Equal(t, "a", im.Username) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: You can use the configuration decoding pattern we have instead of Marshaling/Unmarshaling JSON.
Example:
https://github.com/dapr/components-contrib/blob/master/bindings/alicloud/nacos/nacos.go#L59-L66
https://github.com/dapr/components-contrib/blob/master/bindings/alicloud/nacos/settings.go