-
Notifications
You must be signed in to change notification settings - Fork 81
Initial commit for task end points #691
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
Open
bluepal-prasanthi-moparthi
wants to merge
8
commits into
master
Choose a base branch
from
feature/task-endpoints-328
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+506
−0
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
f34fa61
Initial commit for task end points
bluepal-prasanthi-moparthi f6b9ddf
Initial commit for task end points
bluepal-prasanthi-moparthi 2a52ba6
Merge remote-tracking branch 'origin/feature/task-endpoints-328' into…
bluepal-prasanthi-moparthi 0f89c52
changed printf to logf
bluepal-prasanthi-moparthi 4ccb44d
added logs and added params in test case
bluepal-prasanthi-moparthi 835fc4d
modifed test casses added validation for task options and dbName
bluepal-prasanthi-moparthi 8175169
changes in validator
bluepal-prasanthi-moparthi bb7e54e
chore: trigger CI with empty commit
bluepal-prasanthi-moparthi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,4 +36,5 @@ type Client interface { | |
ClientAdmin | ||
ClientAsyncJob | ||
ClientFoxx | ||
ClientTasks | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// DISCLAIMER | ||
// | ||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
// Copyright holder is ArangoDB GmbH, Cologne, Germany | ||
|
||
package arangodb | ||
|
||
import ( | ||
"context" | ||
) | ||
|
||
// ClientTasks defines the interface for managing tasks in ArangoDB. | ||
type ClientTasks interface { | ||
// Task retrieves an existing task by its ID. | ||
// If no task with the given ID exists, a NotFoundError is returned. | ||
Task(ctx context.Context, databaseName string, id string) (Task, error) | ||
|
||
// Tasks returns a list of all tasks on the server. | ||
Tasks(ctx context.Context, databaseName string) ([]Task, error) | ||
|
||
// CreateTask creates a new task with the specified options. | ||
CreateTask(ctx context.Context, databaseName string, options *TaskOptions) (Task, error) | ||
|
||
// If a task with the given ID already exists, a Conflict error is returned. | ||
CreateTaskWithID(ctx context.Context, databaseName string, id string, options *TaskOptions) (Task, error) | ||
|
||
// RemoveTask deletes an existing task by its ID. | ||
RemoveTask(ctx context.Context, databaseName string, id string) error | ||
} | ||
|
||
// TaskOptions contains options for creating a new task. | ||
type TaskOptions struct { | ||
// ID is an optional identifier for the task. | ||
ID string `json:"id,omitempty"` | ||
// Name is an optional name for the task. | ||
Name string `json:"name,omitempty"` | ||
|
||
// Command is the JavaScript code to be executed. | ||
Command string `json:"command"` | ||
|
||
// Params are optional parameters passed to the command. | ||
Params interface{} `json:"params,omitempty"` | ||
|
||
// Period is the interval (in seconds) at which the task runs periodically. | ||
// If zero, the task runs once after the offset. | ||
Period int64 `json:"period,omitempty"` | ||
|
||
// Offset is the delay (in milliseconds) before the task is first executed. | ||
Offset float64 `json:"offset,omitempty"` | ||
} | ||
|
||
// Task provides access to a single task on the server. | ||
type Task interface { | ||
// ID returns the ID of the task. | ||
ID() string | ||
|
||
// Name returns the name of the task. | ||
Name() string | ||
|
||
// Command returns the JavaScript code of the task. | ||
Command() string | ||
|
||
// Params returns the parameters of the task. | ||
Params(result interface{}) error | ||
|
||
// Period returns the period (in seconds) of the task. | ||
Period() int64 | ||
|
||
// Offset returns the offset (in milliseconds) of the task. | ||
Offset() float64 | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
// DISCLAIMER | ||
// | ||
// Copyright 2024 ArangoDB GmbH, Cologne, Germany | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// | ||
// Copyright holder is ArangoDB GmbH, Cologne, Germany | ||
// | ||
|
||
package arangodb | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
|
||
"github.com/pkg/errors" | ||
|
||
"github.com/arangodb/go-driver/v2/arangodb/shared" | ||
"github.com/arangodb/go-driver/v2/connection" | ||
) | ||
|
||
type clientTask struct { | ||
client *client | ||
} | ||
|
||
// newClientTask initializes a new task client with the given database name. | ||
func newClientTask(client *client) *clientTask { | ||
return &clientTask{ | ||
client: client, | ||
} | ||
} | ||
|
||
// will check all methods in ClientTasks are implemented with the clientTask struct. | ||
var _ ClientTasks = &clientTask{} | ||
|
||
type taskResponse struct { | ||
ID string `json:"id,omitempty"` | ||
Name string `json:"name,omitempty"` | ||
Command string `json:"command,omitempty"` | ||
Params json.RawMessage `json:"params,omitempty"` | ||
Period int64 `json:"period,omitempty"` | ||
Offset float64 `json:"offset,omitempty"` | ||
} | ||
|
||
func newTask(client *client, resp *taskResponse) Task { | ||
return &task{ | ||
client: client, | ||
id: resp.ID, | ||
name: resp.Name, | ||
command: resp.Command, | ||
params: resp.Params, | ||
period: resp.Period, | ||
offset: resp.Offset, | ||
} | ||
} | ||
|
||
type task struct { | ||
client *client | ||
id string | ||
name string | ||
command string | ||
params json.RawMessage | ||
period int64 | ||
offset float64 | ||
} | ||
|
||
// Task interface implementation for the task struct. | ||
func (t *task) ID() string { | ||
return t.id | ||
} | ||
|
||
func (t *task) Name() string { | ||
return t.name | ||
} | ||
|
||
func (t *task) Command() string { | ||
return t.command | ||
} | ||
|
||
func (t *task) Params(result interface{}) error { | ||
if t.params == nil { | ||
return nil | ||
} | ||
return json.Unmarshal(t.params, result) | ||
} | ||
|
||
func (t *task) Period() int64 { | ||
return t.period | ||
} | ||
|
||
func (t *task) Offset() float64 { | ||
return t.offset | ||
} | ||
|
||
// Tasks retrieves all tasks from the specified database. | ||
// Retuns a slice of Task objects representing the tasks in the database. | ||
func (c clientTask) Tasks(ctx context.Context, databaseName string) ([]Task, error) { | ||
urlEndpoint := connection.NewUrl("_db", url.PathEscape(databaseName), "_api", "tasks") | ||
response := make([]taskResponse, 0) // Direct array response | ||
resp, err := connection.CallGet(ctx, c.client.connection, urlEndpoint, &response) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
switch code := resp.Code(); code { | ||
case http.StatusOK: | ||
// Convert the response to Task objects | ||
result := make([]Task, len(response)) | ||
for i, task := range response { | ||
result[i] = newTask(c.client, &task) | ||
} | ||
return result, nil | ||
default: | ||
// Attempt to get error details from response headers or body | ||
return nil, shared.NewResponseStruct().AsArangoErrorWithCode(code) | ||
} | ||
} | ||
|
||
// Task retrieves a specific task by its ID from the specified database. | ||
// If the task does not exist, it returns an error. | ||
// If the task exists, it returns a Task object. | ||
func (c clientTask) Task(ctx context.Context, databaseName string, id string) (Task, error) { | ||
urlEndpoint := connection.NewUrl("_db", url.PathEscape(databaseName), "_api", "tasks", url.PathEscape(id)) | ||
response := struct { | ||
taskResponse `json:",inline"` | ||
shared.ResponseStruct `json:",inline"` | ||
}{} | ||
|
||
resp, err := connection.CallGet(ctx, c.client.connection, urlEndpoint, &response) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
switch code := resp.Code(); code { | ||
case http.StatusOK: | ||
return newTask(c.client, &response.taskResponse), nil | ||
default: | ||
return nil, response.AsArangoError() | ||
} | ||
} | ||
|
||
// validateTaskOptions checks if required fields in TaskOptions are set. | ||
func validateTaskOptions(options *TaskOptions) error { | ||
if options == nil { | ||
return errors.New("TaskOptions must not be nil") | ||
} | ||
if options.Command == "" { | ||
return errors.New("TaskOptions.Command must not be empty") | ||
} | ||
return nil | ||
} | ||
|
||
// CreateTask creates a new task with the specified options in the given database. | ||
// If the task already exists (based on ID), it will update the existing task. | ||
// If the task does not exist, it will create a new task. | ||
// The options parameter contains the task configuration such as name, command, parameters, period, and offset. | ||
// The ID field in options is optional; if provided, it will be used as the task identifier. | ||
func (c clientTask) CreateTask(ctx context.Context, databaseName string, options *TaskOptions) (Task, error) { | ||
if err := validateTaskOptions(options); err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
var urlEndpoint string | ||
if options.ID != "" { | ||
urlEndpoint = connection.NewUrl("_db", url.PathEscape(databaseName), "_api", "tasks", url.PathEscape(options.ID)) | ||
} else { | ||
urlEndpoint = connection.NewUrl("_db", url.PathEscape(databaseName), "_api", "tasks") | ||
} | ||
// Prepare the request body | ||
createRequest := struct { | ||
ID string `json:"id,omitempty"` | ||
Name string `json:"name,omitempty"` | ||
Command string `json:"command,omitempty"` | ||
Params json.RawMessage `json:"params,omitempty"` | ||
Period int64 `json:"period,omitempty"` | ||
Offset float64 `json:"offset,omitempty"` | ||
}{ | ||
ID: options.ID, | ||
Name: options.Name, | ||
Command: options.Command, | ||
Period: options.Period, | ||
Offset: options.Offset, | ||
} | ||
|
||
if options.Params != nil { | ||
// Marshal Params into JSON | ||
// This allows for complex parameters to be passed as JSON objects | ||
// and ensures that the Params field is correctly formatted. | ||
raw, err := json.Marshal(options.Params) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
createRequest.Params = raw | ||
} | ||
|
||
response := struct { | ||
shared.ResponseStruct `json:",inline"` | ||
taskResponse `json:",inline"` | ||
}{} | ||
|
||
resp, err := connection.CallPost(ctx, c.client.connection, urlEndpoint, &response, &createRequest) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
|
||
switch code := resp.Code(); code { | ||
case http.StatusCreated, http.StatusOK: | ||
return newTask(c.client, &response.taskResponse), nil | ||
default: | ||
return nil, response.AsArangoError() | ||
} | ||
} | ||
|
||
// RemoveTask deletes an existing task by its ID from the specified database. | ||
// If the task is successfully removed, it returns nil. | ||
// If the task does not exist or there is an error during the removal, it returns an error. | ||
// The ID parameter is the identifier of the task to be removed. | ||
// The databaseName parameter specifies the database from which the task should be removed. | ||
// It constructs the URL endpoint for the task API and calls the DELETE method to remove the task | ||
func (c clientTask) RemoveTask(ctx context.Context, databaseName string, id string) error { | ||
urlEndpoint := connection.NewUrl("_db", url.PathEscape(databaseName), "_api", "tasks", url.PathEscape(id)) | ||
|
||
resp, err := connection.CallDelete(ctx, c.client.connection, urlEndpoint, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
switch code := resp.Code(); code { | ||
case http.StatusAccepted, http.StatusOK: | ||
return nil | ||
default: | ||
return shared.NewResponseStruct().AsArangoErrorWithCode(code) | ||
} | ||
} | ||
|
||
// CreateTaskWithID creates a new task with the specified ID and options. | ||
// If a task with the given ID already exists, it returns a Conflict error. | ||
// If the task does not exist, it creates a new task with the provided options. | ||
func (c clientTask) CreateTaskWithID(ctx context.Context, databaseName string, id string, options *TaskOptions) (Task, error) { | ||
// Check if task already exists | ||
existingTask, err := c.Task(ctx, databaseName, id) | ||
if err == nil && existingTask != nil { | ||
return nil, &shared.ArangoError{ | ||
Code: http.StatusConflict, | ||
ErrorMessage: fmt.Sprintf("Task with ID %s already exists", id), | ||
} | ||
} | ||
|
||
// Set the ID and call CreateTask | ||
options.ID = id | ||
return c.CreateTask(ctx, databaseName, options) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Please use pointers to allow skipping specific fields without passing any default value, similarly to
go-driver/v2/arangodb/view_arango_search.go
Line 82 in 10a58c3