Skip to content

Commit 7aca79c

Browse files
authored
feat: breaking plugins to mods for easier composition (#47)
Signed-off-by: Kush <[email protected]>
1 parent 4bbe355 commit 7aca79c

File tree

84 files changed

+6677
-8355
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+6677
-8355
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
with:
2727
skip-go-installation: true
2828

29-
test:
29+
unit:
3030
runs-on: ubuntu-latest
3131
steps:
3232
- name: Checkout

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Optimus helps your organization to build & manage data pipelines with ease.
2020
- Dry run query: Before SQL query is scheduled for transformation, during
2121
deployment query will be dry-run to make sure it passes basic sanity
2222
checks
23-
- Sink BigQuery tables to Kafka [using additional hook]
23+
- Sink BigQuery tables to Kafka [using additional plugins]
2424
- Extensibility to support Python transformation
2525
- Git based specification management
2626
- REST/GRPC based specification management

api/handler/v1/adapter.go

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package v1
22

33
import (
4-
"context"
54
"fmt"
65
"strings"
76
"time"
87

8+
"google.golang.org/protobuf/types/known/timestamppb"
9+
910
"github.com/odpf/optimus/core/tree"
1011

1112
"github.com/golang/protobuf/proto"
@@ -18,8 +19,7 @@ import (
1819

1920
// Note: all config keys will be converted to upper case automatically
2021
type Adapter struct {
21-
supportedTaskRepo models.TaskPluginRepository
22-
supportedHookRepo models.HookRepo
22+
pluginRepo models.PluginRepository
2323
supportedDatastoreRepo models.DatastoreRepo
2424
}
2525

@@ -51,7 +51,7 @@ func (adapt *Adapter) FromJobProto(spec *pb.JobSpecification) (models.JobSpec, e
5151
return models.JobSpec{}, err
5252
}
5353

54-
execUnit, err := adapt.supportedTaskRepo.GetByName(spec.TaskName)
54+
execUnit, err := adapt.pluginRepo.GetByName(spec.TaskName)
5555
if err != nil {
5656
return models.JobSpec{}, err
5757
}
@@ -149,14 +149,6 @@ func prepareWindow(windowSize, windowOffset, truncateTo string) (models.JobSpecT
149149
}
150150

151151
func (adapt *Adapter) ToJobProto(spec models.JobSpec) (*pb.JobSpecification, error) {
152-
if spec.Task.Unit == nil {
153-
return nil, errors.New("task unit cannot be nil")
154-
}
155-
taskSchema, err := spec.Task.Unit.GetTaskSchema(context.Background(), models.GetTaskSchemaRequest{})
156-
if err != nil {
157-
return nil, err
158-
}
159-
160152
adaptedHook, err := adapt.ToHookProto(spec.Hooks)
161153
if err != nil {
162154
return nil, err
@@ -179,7 +171,7 @@ func (adapt *Adapter) ToJobProto(spec models.JobSpec) (*pb.JobSpecification, err
179171
StartDate: spec.Schedule.StartDate.Format(models.JobDatetimeLayout),
180172
DependsOnPast: spec.Behavior.DependsOnPast,
181173
CatchUp: spec.Behavior.CatchUp,
182-
TaskName: taskSchema.Name,
174+
TaskName: spec.Task.Unit.Info().Name,
183175
WindowSize: spec.Task.Window.SizeString(),
184176
WindowOffset: spec.Task.Window.OffsetString(),
185177
WindowTruncateTo: spec.Task.Window.TruncateTo,
@@ -325,10 +317,7 @@ func (adapt *Adapter) ToInstanceProto(spec models.InstanceSpec) (*pb.InstanceSpe
325317
Type: pb.InstanceSpecData_Type(pb.InstanceSpecData_Type_value[strings.ToUpper(asset.Type)]),
326318
})
327319
}
328-
schdAt, err := ptypes.TimestampProto(spec.ScheduledAt)
329-
if err != nil {
330-
return nil, err
331-
}
320+
schdAt := timestamppb.New(spec.ScheduledAt)
332321
return &pb.InstanceSpec{
333322
JobName: spec.Job.Name,
334323
ScheduledAt: schdAt,
@@ -368,7 +357,7 @@ func (adapt *Adapter) FromInstanceProto(conf *pb.InstanceSpec) (models.InstanceS
368357
func (adapt *Adapter) FromHookProto(hooksProto []*pb.JobSpecHook) ([]models.JobSpecHook, error) {
369358
var hooks []models.JobSpecHook
370359
for _, hook := range hooksProto {
371-
hookUnit, err := adapt.supportedHookRepo.GetByName(hook.Name)
360+
hookUnit, err := adapt.pluginRepo.GetByName(hook.Name)
372361
if err != nil {
373362
return nil, err
374363
}
@@ -399,12 +388,8 @@ func (adapt *Adapter) ToHookProto(hooks []models.JobSpecHook) (protoHooks []*pb.
399388
})
400389
}
401390

402-
schema, err := hook.Unit.GetHookSchema(context.Background(), models.GetHookSchemaRequest{})
403-
if err != nil {
404-
return nil, err
405-
}
406391
protoHooks = append(protoHooks, &pb.JobSpecHook{
407-
Name: schema.Name,
392+
Name: hook.Unit.Info().Name,
408393
Config: hookConfigs,
409394
})
410395
}
@@ -451,10 +436,7 @@ func (adapt *Adapter) ToReplayExecutionTreeNode(res *tree.TreeNode) (*pb.ReplayE
451436
}
452437
for _, run := range res.Runs.Values() {
453438
runTime := run.(time.Time)
454-
timestampPb, err := ptypes.TimestampProto(runTime)
455-
if err != nil {
456-
return nil, err
457-
}
439+
timestampPb := timestamppb.New(runTime)
458440
response.Runs = append(response.Runs, timestampPb)
459441
}
460442
for _, dep := range res.Dependents {
@@ -467,11 +449,9 @@ func (adapt *Adapter) ToReplayExecutionTreeNode(res *tree.TreeNode) (*pb.ReplayE
467449
return response, nil
468450
}
469451

470-
func NewAdapter(supportedTaskRepo models.TaskPluginRepository,
471-
supportedHookRepo models.HookRepo, datastoreRepo models.DatastoreRepo) *Adapter {
452+
func NewAdapter(pluginRepo models.PluginRepository, datastoreRepo models.DatastoreRepo) *Adapter {
472453
return &Adapter{
473-
supportedTaskRepo: supportedTaskRepo,
474-
supportedHookRepo: supportedHookRepo,
454+
pluginRepo: pluginRepo,
475455
supportedDatastoreRepo: datastoreRepo,
476456
}
477457
}

api/handler/v1/adapter_test.go

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package v1_test
22

33
import (
4-
"context"
54
"reflect"
65
"testing"
76
"time"
@@ -31,25 +30,17 @@ func TestAdapter(t *testing.T) {
3130
assert.Equal(t, replayExecutionTreeNode.Dependents[0].JobName, "nested-job-name")
3231
})
3332
t.Run("should successfully parse job spec to and from proto", func(t *testing.T) {
34-
execUnit1 := new(mock.TaskPlugin)
35-
execUnit1.On("GetTaskSchema", context.Background(), models.GetTaskSchemaRequest{}).Return(models.GetTaskSchemaResponse{
33+
execUnit1 := new(mock.BasePlugin)
34+
execUnit1.On("PluginInfo").Return(&models.PluginInfoResponse{
3635
Name: "sample-task",
3736
}, nil)
3837
defer execUnit1.AssertExpectations(t)
3938

40-
allTasksRepo := new(mock.SupportedTaskRepo)
41-
allTasksRepo.On("GetByName", "sample-task").Return(execUnit1, nil)
42-
defer allTasksRepo.AssertExpectations(t)
43-
44-
hookUnit1 := new(mock.HookPlugin)
45-
hookUnit1.On("GetHookSchema", context.Background(), models.GetHookSchemaRequest{}).Return(models.GetHookSchemaResponse{
46-
Name: "sample-hook",
39+
pluginRepo := new(mock.SupportedPluginRepo)
40+
pluginRepo.On("GetByName", "sample-task").Return(&models.Plugin{
41+
Base: execUnit1,
4742
}, nil)
48-
defer hookUnit1.AssertExpectations(t)
49-
50-
allHookRepo := new(mock.SupportedHookRepo)
51-
allHookRepo.On("GetByName", "sample-hook").Return(hookUnit1, nil)
52-
defer allHookRepo.AssertExpectations(t)
43+
adapter := v1.NewAdapter(pluginRepo, nil)
5344

5445
jobSpec := models.JobSpec{
5546
Name: "test-job",
@@ -76,7 +67,7 @@ func TestAdapter(t *testing.T) {
7667
},
7768
},
7869
Task: models.JobSpecTask{
79-
Unit: execUnit1,
70+
Unit: &models.Plugin{Base: execUnit1},
8071
Config: models.JobSpecConfigs{
8172
{
8273
Name: "DO",
@@ -106,12 +97,11 @@ func TestAdapter(t *testing.T) {
10697
Value: "this",
10798
},
10899
},
109-
Unit: hookUnit1,
100+
Unit: &models.Plugin{Base: execUnit1},
110101
},
111102
},
112103
}
113104

114-
adapter := v1.NewAdapter(allTasksRepo, allHookRepo, nil)
115105
inProto, err := adapter.ToJobProto(jobSpec)
116106
assert.Nil(t, err)
117107
original, err := adapter.FromJobProto(inProto)

api/handler/v1/runtime.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"strings"
88
"time"
99

10+
"google.golang.org/protobuf/types/known/timestamppb"
11+
1012
"google.golang.org/protobuf/types/known/structpb"
1113

1214
"github.com/odpf/optimus/core/tree"
@@ -508,10 +510,7 @@ func (sv *RuntimeServiceServer) JobStatus(ctx context.Context, req *pb.JobStatus
508510

509511
var adaptedJobStatus []*pb.JobStatus
510512
for _, jobStatus := range jobStatuses {
511-
ts, err := ptypes.TimestampProto(jobStatus.ScheduledAt)
512-
if err != nil {
513-
return nil, status.Errorf(codes.Internal, "%s: failed to parse time for %s", err.Error(), req.GetJobName())
514-
}
513+
ts := timestamppb.New(jobStatus.ScheduledAt)
515514
adaptedJobStatus = append(adaptedJobStatus, &pb.JobStatus{
516515
State: jobStatus.State.String(),
517516
ScheduledAt: ts,
@@ -574,11 +573,8 @@ func (sv *RuntimeServiceServer) GetWindow(ctx context.Context, req *pb.GetWindow
574573
return nil, status.Error(codes.Internal, err.Error())
575574
}
576575

577-
windowStart, err1 := ptypes.TimestampProto(window.GetStart(scheduledTime))
578-
windowEnd, err2 := ptypes.TimestampProto(window.GetEnd(scheduledTime))
579-
if err1 != nil || err2 != nil {
580-
return nil, status.Errorf(codes.Internal, "%s: failed to convert timestamp %s", err.Error(), scheduledTime)
581-
}
576+
windowStart := timestamppb.New(window.GetStart(scheduledTime))
577+
windowEnd := timestamppb.New(window.GetEnd(scheduledTime))
582578

583579
return &pb.GetWindowResponse{
584580
Start: windowStart,

0 commit comments

Comments
 (0)