Skip to content
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

fix: clean up database metadata #1115

Merged
merged 1 commit into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
352 changes: 176 additions & 176 deletions backend/protos/xyz/block/ftl/v1/schema/schema.pb.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion backend/protos/xyz/block/ftl/v1/schema/schema.proto
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@

message MetadataDatabases {
optional Position pos = 1;
repeated Database calls = 2;
repeated Ref calls = 2;

Check failure on line 141 in backend/protos/xyz/block/ftl/v1/schema/schema.proto

View workflow job for this annotation

GitHub Actions / Proto Breaking Change Check

Field "2" on message "MetadataDatabases" changed type from "xyz.block.ftl.v1.schema.Database" to "xyz.block.ftl.v1.schema.Ref".
}

message MetadataIngress {
Expand Down
8 changes: 0 additions & 8 deletions backend/schema/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,3 @@ func DatabaseFromProto(s *schemapb.Database) *Database {
Comments: s.Comments,
}
}

func databaseListToSchema(s []*schemapb.Database) []*Database {
var out []*Database
for _, n := range s {
out = append(out, DatabaseFromProto(n))
}
return out
}
6 changes: 3 additions & 3 deletions backend/schema/metadatadatabases.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
type MetadataDatabases struct {
Pos Position `parser:"" protobuf:"1,optional"`

Calls []*Database `parser:"'+' 'database' 'calls' @@ (',' @@)*" protobuf:"2"`
Calls []*Ref `parser:"'+' 'database' 'calls' @@ (',' @@)*" protobuf:"2"`
}

var _ Metadata = (*MetadataDatabases)(nil)
Expand All @@ -35,7 +35,7 @@ func (m *MetadataDatabases) String() string {
w += len(str)
fmt.Fprint(out, str)
}
fmt.Fprintln(out)
fmt.Fprint(out)
return out.String()
}

Expand All @@ -51,6 +51,6 @@ func (*MetadataDatabases) schemaMetadata() {}
func (m *MetadataDatabases) ToProto() proto.Message {
return &schemapb.MetadataDatabases{
Pos: posToProto(m.Pos),
Calls: nodeListToProto[*schemapb.Database](m.Calls),
Calls: nodeListToProto[*schemapb.Ref](m.Calls),
}
}
2 changes: 1 addition & 1 deletion backend/schema/protobuf_dec.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func metadataToSchema(s *schemapb.Metadata) Metadata {
case *schemapb.Metadata_Databases:
return &MetadataDatabases{
Pos: posFromProto(s.Databases.Pos),
Calls: databaseListToSchema(s.Databases.Calls),
Calls: refListToSchema(s.Databases.Calls),
}

case *schemapb.Metadata_Ingress:
Expand Down
26 changes: 19 additions & 7 deletions backend/schema/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ func TestSchemaString(t *testing.T) {
module todo {
config configValue String

secret secretValue String

database testdb

data CreateRequest {
name {String: String}? +alias json "rqn"
}
Expand All @@ -39,10 +43,8 @@ module todo {
when Time
}

secret secretValue String

verb create(todo.CreateRequest) todo.CreateResponse
+calls todo.destroy
+calls todo.destroy +database calls todo.testdb

verb destroy(builtin.HttpRequest<todo.DestroyRequest>) builtin.HttpResponse<todo.DestroyResponse, String>
+ingress http GET /todo/destroy/{id}
Expand Down Expand Up @@ -95,6 +97,9 @@ func TestVisit(t *testing.T) {
Module
Config
String
Secret
String
Database
Data
Field
Optional
Expand All @@ -115,13 +120,13 @@ Module
String
Field
Time
Secret
String
Verb
Ref
Ref
MetadataCalls
Ref
MetadataDatabases
Ref
Verb
Ref
Ref
Expand Down Expand Up @@ -365,6 +370,7 @@ func TestParseModule(t *testing.T) {
module todo {
config configValue String
secret secretValue String
database testdb

data CreateRequest {
name {String: String}? +alias json "rqn"
Expand All @@ -381,7 +387,7 @@ module todo {
when Time
}
verb create(todo.CreateRequest) todo.CreateResponse
+calls todo.destroy
+calls todo.destroy +database calls todo.testdb
verb destroy(builtin.HttpRequest<todo.DestroyRequest>) builtin.HttpResponse<todo.DestroyResponse, String>
+ingress http GET /todo/destroy/{id}
}
Expand Down Expand Up @@ -429,6 +435,9 @@ var testSchema = MustValidate(&Schema{
Name: "configValue",
Type: &String{},
},
&Database{
Name: "testdb",
},
&Data{
Name: "CreateRequest",
Fields: []*Field{
Expand Down Expand Up @@ -457,7 +466,10 @@ var testSchema = MustValidate(&Schema{
&Verb{Name: "create",
Request: &Ref{Module: "todo", Name: "CreateRequest"},
Response: &Ref{Module: "todo", Name: "CreateResponse"},
Metadata: []Metadata{&MetadataCalls{Calls: []*Ref{{Module: "todo", Name: "destroy"}}}}},
Metadata: []Metadata{
&MetadataCalls{Calls: []*Ref{{Module: "todo", Name: "destroy"}}},
&MetadataDatabases{Calls: []*Ref{{Module: "todo", Name: "testdb"}}},
}},
&Verb{Name: "destroy",
Request: &Ref{Module: "builtin", Name: "HttpRequest", TypeParameters: []Type{&Ref{Module: "todo", Name: "DestroyRequest"}}},
Response: &Ref{Module: "builtin", Name: "HttpResponse", TypeParameters: []Type{&Ref{Module: "todo", Name: "DestroyResponse"}, &String{}}},
Expand Down
39 changes: 30 additions & 9 deletions backend/schema/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func Validate(schema *Schema) (*Schema, error) {
case *Ref:
if mdecl := scopes.Resolve(*n); mdecl != nil {
switch decl := mdecl.Symbol.(type) {
case *Verb, *Enum:
case *Verb, *Enum, *Database, *Config, *Secret:
if mdecl.Module != nil {
n.Module = mdecl.Module.Name
}
Expand All @@ -121,7 +121,6 @@ func Validate(schema *Schema) (*Schema, error) {
case *TypeParameter:
default:
merr = append(merr, fmt.Errorf("%s: invalid reference %q at %q", n.Pos, n, mdecl.Symbol.Position()))

}
} else {
merr = append(merr, fmt.Errorf("%s: unknown reference %q", n.Pos, n))
Expand Down Expand Up @@ -209,8 +208,10 @@ func ValidateModule(module *Module) error {
case *Ref:
if mdecl := scopes.Resolve(*n); mdecl != nil {
switch decl := mdecl.Symbol.(type) {
case *Verb, *Enum:
n.Module = mdecl.Module.Name
case *Verb, *Enum, *Database, *Config, *Secret:
if n.Module == "" {
n.Module = mdecl.Module.Name
}
if len(n.TypeParameters) != 0 {
merr = append(merr, fmt.Errorf("%s: reference to %s %q cannot have type parameters",
n.Pos, reflect.TypeOf(decl).Elem().Name(), n.Name))
Expand All @@ -224,7 +225,6 @@ func ValidateModule(module *Module) error {
n.Pos, n.Name, len(n.TypeParameters), len(decl.TypeParameters)))
}
case *TypeParameter:

default:
if n.Module == "" {
merr = append(merr, fmt.Errorf("%s: unqualified reference to invalid %s %q", n.Pos, reflect.TypeOf(decl).Elem().Name(), n))
Expand Down Expand Up @@ -293,16 +293,37 @@ func ValidateModule(module *Module) error {
sort.SliceStable(module.Decls, func(i, j int) bool {
iDecl := module.Decls[i]
jDecl := module.Decls[j]
iType := reflect.TypeOf(iDecl).String()
jType := reflect.TypeOf(jDecl).String()
if iType == jType {
iPriority := getDeclSortingPriority(iDecl)
jPriority := getDeclSortingPriority(jDecl)
if iPriority == jPriority {
return iDecl.GetName() < jDecl.GetName()
}
return iType < jType
return iPriority < jPriority
})
return errors.Join(merr...)
}

// getDeclSortingPriority (used for schema sorting) is pulled out into it's own switch so the Go sumtype check will fail
// if a new Decl is added but not explicitly prioritized
func getDeclSortingPriority(decl Decl) int {
priority := 0
switch decl.(type) {
case *Config:
priority = 1
case *Secret:
priority = 2
case *Database:
priority = 3
case *Enum:
priority = 4
case *Data:
priority = 5
case *Verb:
priority = 6
}
return priority
}

// Sort and de-duplicate errors.
func cleanErrors(merr []error) []error {
if len(merr) == 0 {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/protos/xyz/block/ftl/v1/schema/schema_pb.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 37 additions & 37 deletions go-runtime/compile/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,36 +45,7 @@ func TestExtractModuleSchema(t *testing.T) {
expected := `module one {
config configValue one.Config

data Config {
field String
}

data Nested {
}

data Req {
int Int
int64 Int
float Float
string String
slice [String]
map {String: String}
nested one.Nested
optional one.Nested?
time Time
user two.User +alias json "u"
bytes Bytes
enumRef two.TwoEnum
}

data Resp {
}

data SinkReq {
}

data SourceResp {
}
secret secretValue String

enum Color(String) {
Red("Red")
Expand Down Expand Up @@ -105,7 +76,36 @@ func TestExtractModuleSchema(t *testing.T) {
Two(2)
}

secret secretValue String
data Config {
field String
}

data Nested {
}

data Req {
int Int
int64 Int
float Float
string String
slice [String]
map {String: String}
nested one.Nested
optional one.Nested?
time Time
user two.User +alias json "u"
bytes Bytes
enumRef two.TwoEnum
}

data Resp {
}

data SinkReq {
}

data SourceResp {
}

verb nothing(Unit) Unit

Expand All @@ -124,6 +124,12 @@ func TestExtractModuleSchemaTwo(t *testing.T) {
assert.NoError(t, err)
actual = schema.Normalise(actual)
expected := `module two {
enum TwoEnum(String) {
Red("Red")
Blue("Blue")
Green("Green")
}

data Payload<T> {
body T
}
Expand All @@ -136,12 +142,6 @@ func TestExtractModuleSchemaTwo(t *testing.T) {
user two.User
}

enum TwoEnum(String) {
Red("Red")
Blue("Blue")
Green("Green")
}

verb callsTwo(two.Payload<String>) two.Payload<String>
+calls two.two

Expand Down
Binary file added kotlin-runtime/ftl-runtime/schema.pb
Binary file not shown.
Loading