-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add JSON schema to scheduler strategy (#1254)
This allows using centralized JSON schema definition instead of tagging every `scheduler.Strategy` entry in plugin specs
- Loading branch information
1 parent
5dc9654
commit 1cec01d
Showing
8 changed files
with
172 additions
and
79 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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 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,101 @@ | ||
package scheduler | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/invopop/jsonschema" | ||
) | ||
|
||
type Strategy int | ||
|
||
func (s *Strategy) String() string { | ||
if s == nil { | ||
return "" | ||
} | ||
return AllStrategyNames[*s] | ||
} | ||
|
||
// MarshalJSON implements json.Marshaler. | ||
func (s *Strategy) MarshalJSON() ([]byte, error) { | ||
var b bytes.Buffer | ||
if s == nil { | ||
b.Write([]byte("null")) | ||
return b.Bytes(), nil | ||
} | ||
b.Write([]byte{'"'}) | ||
b.Write([]byte(s.String())) | ||
b.Write([]byte{'"'}) | ||
return b.Bytes(), nil | ||
} | ||
|
||
// UnmarshalJSON implements json.Unmarshaler. | ||
func (s *Strategy) UnmarshalJSON(b []byte) error { | ||
var name string | ||
if err := json.Unmarshal(b, &name); err != nil { | ||
return err | ||
} | ||
strategy, err := StrategyForName(name) | ||
if err != nil { | ||
return err | ||
} | ||
*s = strategy | ||
return nil | ||
} | ||
|
||
func (s *Strategy) Validate() error { | ||
if s == nil { | ||
return errors.New("scheduler strategy is nil") | ||
} | ||
for _, strategy := range AllStrategies { | ||
if strategy == *s { | ||
return nil | ||
} | ||
} | ||
return fmt.Errorf("unknown scheduler strategy: %d", s) | ||
} | ||
|
||
// JSONSchema uses value receiver because of https://github.com/invopop/jsonschema/issues/102 | ||
func (Strategy) JSONSchema() *jsonschema.Schema { | ||
enum := make([]any, len(AllStrategyNames)) | ||
for i, s := range AllStrategyNames { | ||
enum[i] = s | ||
} | ||
return &jsonschema.Schema{ | ||
Type: "string", | ||
Enum: enum, | ||
Default: AllStrategyNames[StrategyDFS], | ||
Title: "CloudQuery scheduling strategy", | ||
} | ||
} | ||
|
||
var AllStrategies = Strategies{StrategyDFS, StrategyRoundRobin, StrategyShuffle} | ||
var AllStrategyNames = [...]string{ | ||
StrategyDFS: "dfs", | ||
StrategyRoundRobin: "round-robin", | ||
StrategyShuffle: "shuffle", | ||
} | ||
|
||
func StrategyForName(s string) (Strategy, error) { | ||
for i, name := range AllStrategyNames { | ||
if name == s { | ||
return AllStrategies[i], nil | ||
} | ||
} | ||
return StrategyDFS, fmt.Errorf("unknown scheduler strategy: %s", s) | ||
} | ||
|
||
type Strategies []Strategy | ||
|
||
func (s Strategies) String() string { | ||
var buffer bytes.Buffer | ||
for i, strategy := range s { | ||
if i > 0 { | ||
buffer.WriteString(", ") | ||
} | ||
buffer.WriteString(strategy.String()) | ||
} | ||
return buffer.String() | ||
} |
This file contains 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,17 @@ | ||
{ | ||
"$schema": "https://json-schema.org/draft/2020-12/schema", | ||
"$id": "https://github.com/cloudquery/plugin-sdk/v4/scheduler/strategy", | ||
"$ref": "#/$defs/Strategy", | ||
"$defs": { | ||
"Strategy": { | ||
"type": "string", | ||
"enum": [ | ||
"dfs", | ||
"round-robin", | ||
"shuffle" | ||
], | ||
"title": "CloudQuery scheduling strategy", | ||
"default": "dfs" | ||
} | ||
} | ||
} |
This file contains 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,22 @@ | ||
package scheduler_test | ||
|
||
import ( | ||
_ "embed" | ||
"encoding/json" | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/cloudquery/plugin-sdk/v4/scheduler" | ||
"github.com/invopop/jsonschema" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
//go:embed strategy.json | ||
var jsonSchema string | ||
|
||
func TestStrategy_JSONSchema(t *testing.T) { | ||
sc := (&jsonschema.Reflector{RequiredFromJSONSchemaTags: true}).ReflectFromType(reflect.TypeOf(scheduler.StrategyDFS)) | ||
data, err := json.MarshalIndent(sc, "", " ") | ||
require.NoError(t, err) | ||
require.JSONEq(t, string(data)+"\n", jsonSchema) | ||
} |
1cec01d
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.
⏱️ Benchmark results