diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03c3a23804..e834e33229 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: - name: Build Cache uses: ./.github/actions/build-cache - name: Test - run: mvn test --batch-mode + run: mvn -f kotlin-runtime/ftl-runtime -B test test: name: Test Go runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 58fc733479..a898cafddf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -112,9 +112,9 @@ jobs: cache: "maven" - name: Publish JARs # Snapshots are published first, then the tagged release run: | - mvn -U -B clean deploy -P release - mvn -B versions:set -DnewVersion="$(git describe --tags --abbrev=0 | cut -c2-)" -DprocessAllModules -DgenerateBackupPoms=false - mvn -U -B clean deploy -P release + mvn -f kotlin-runtime/ftl-runtime -U -B clean deploy -P release + mvn -f kotlin-runtime/ftl-runtime -B versions:set -DnewVersion="$(git describe --tags --abbrev=0 | cut -c2-)" -DprocessAllModules -DgenerateBackupPoms=false + mvn -f kotlin-runtime/ftl-runtime -U -B clean deploy -P release git clean -f ./*.flattened_pom.xml env: SIGN_KEY_PASS: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.github/workflows/writecache.yml b/.github/workflows/writecache.yml index 242de489d2..6c3b881e79 100644 --- a/.github/workflows/writecache.yml +++ b/.github/workflows/writecache.yml @@ -24,7 +24,7 @@ jobs: - name: Rebuild All run: bit - name: Download Maven Dependencies - run: mvn dependency:resolve --batch-mode + run: mvn -f kotlin-runtime/ftl-runtime dependency:resolve --batch-mode - name: Download Go Dependencies run: go mod download -x - id: find-go-build-cache diff --git a/Bitfile b/Bitfile index 2d5d5159ea..c17c661ad0 100644 --- a/Bitfile +++ b/Bitfile @@ -27,7 +27,7 @@ PROTO_OUT = backend/protos/xyz/block/ftl/v1/ftlv1connect/ftl.connect.go \ COMMON_LOG_IN = internal/log/api.go COMMON_LOG_OUT = internal/log/log_level_string.go -KT_RUNTIME_IN = kotlin-runtime/ftl-runtime/**/*.{kt,kts} pom.xml kotlin-runtime/ftl-runtime/**/pom.xml +KT_RUNTIME_IN = kotlin-runtime/ftl-runtime/**/*.{kt,kts} kotlin-runtime/ftl-runtime/**/pom.xml KT_RUNTIME_OUT = kotlin-runtime/ftl-runtime/target/ftl-runtime-1.0-SNAPSHOT.jar KT_RUNTIME_RUNNER_TEMPLATE_OUT = build/template/ftl/jars/ftl-runtime.jar @@ -113,9 +113,8 @@ kotlin-runtime/external-module-template.zip: kotlin-runtime/external-module-temp %{KT_RUNTIME_OUT}: %{KT_RUNTIME_IN} %{PROTO_IN} # TODO: Figure out how to make Maven build completely offline. Bizarrely "-o" does not do this. build: - mvn -B -N install - mvn -Dmaven.test.skip=true -B -pl :ftl-runtime install - +clean: mvn -B -pl :ftl-runtime clean + mvn -f kotlin-runtime/ftl-runtime -Dmaven.test.skip=true -B install + +clean: mvn -f kotlin-runtime/ftl-runtime -B clean %(dirname %{KT_RUNTIME_RUNNER_TEMPLATE_OUT})%: build: install -m 0700 -d %{OUT} diff --git a/Dockerfile.controller b/Dockerfile.controller index 15e80ed559..7510ec7f03 100644 --- a/Dockerfile.controller +++ b/Dockerfile.controller @@ -10,7 +10,7 @@ WORKDIR /src # Seed some of the most common tools - this will be cached RUN go version -RUN mvn -B --version +RUN mvn -f kotlin-runtime/ftl-runtime -B --version # Download Go dependencies separately so Docker will cache them COPY go.mod go.sum ./ diff --git a/Dockerfile.runner b/Dockerfile.runner index 39d0f99441..603bfabd5f 100644 --- a/Dockerfile.runner +++ b/Dockerfile.runner @@ -12,7 +12,7 @@ RUN hermit install openjre-18.0.2.1_1 RUN hermit uninstall openjre RUN hermit install jbr RUN go version -RUN mvn -B --version +RUN mvn -f kotlin-runtime/ftl-runtime -B --version WORKDIR /src diff --git a/backend/controller/sql/db.go b/backend/controller/sql/db.go deleted file mode 100644 index 953db2655e..0000000000 --- a/backend/controller/sql/db.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.25.0 - -package sql - -import ( - "context" - - "github.com/jackc/pgx/v5" - "github.com/jackc/pgx/v5/pgconn" -) - -type DBTX interface { - Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) - Query(context.Context, string, ...interface{}) (pgx.Rows, error) - QueryRow(context.Context, string, ...interface{}) pgx.Row -} - -func New(db DBTX) *Queries { - return &Queries{db: db} -} - -type Queries struct { - db DBTX -} - -func (q *Queries) WithTx(tx pgx.Tx) *Queries { - return &Queries{ - db: tx, - } -} diff --git a/backend/controller/sql/models.go b/backend/controller/sql/models.go deleted file mode 100644 index b9ab06e1de..0000000000 --- a/backend/controller/sql/models.go +++ /dev/null @@ -1,270 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.25.0 - -package sql - -import ( - "database/sql/driver" - "encoding/json" - "fmt" - "time" - - "github.com/TBD54566975/ftl/backend/schema" - "github.com/TBD54566975/ftl/internal/model" - "github.com/alecthomas/types/optional" -) - -type ControllerState string - -const ( - ControllerStateLive ControllerState = "live" - ControllerStateDead ControllerState = "dead" -) - -func (e *ControllerState) Scan(src interface{}) error { - switch s := src.(type) { - case []byte: - *e = ControllerState(s) - case string: - *e = ControllerState(s) - default: - return fmt.Errorf("unsupported scan type for ControllerState: %T", src) - } - return nil -} - -type NullControllerState struct { - ControllerState ControllerState - Valid bool // Valid is true if ControllerState is not NULL -} - -// Scan implements the Scanner interface. -func (ns *NullControllerState) Scan(value interface{}) error { - if value == nil { - ns.ControllerState, ns.Valid = "", false - return nil - } - ns.Valid = true - return ns.ControllerState.Scan(value) -} - -// Value implements the driver Valuer interface. -func (ns NullControllerState) Value() (driver.Value, error) { - if !ns.Valid { - return nil, nil - } - return string(ns.ControllerState), nil -} - -type EventType string - -const ( - EventTypeCall EventType = "call" - EventTypeLog EventType = "log" - EventTypeDeploymentCreated EventType = "deployment_created" - EventTypeDeploymentUpdated EventType = "deployment_updated" -) - -func (e *EventType) Scan(src interface{}) error { - switch s := src.(type) { - case []byte: - *e = EventType(s) - case string: - *e = EventType(s) - default: - return fmt.Errorf("unsupported scan type for EventType: %T", src) - } - return nil -} - -type NullEventType struct { - EventType EventType - Valid bool // Valid is true if EventType is not NULL -} - -// Scan implements the Scanner interface. -func (ns *NullEventType) Scan(value interface{}) error { - if value == nil { - ns.EventType, ns.Valid = "", false - return nil - } - ns.Valid = true - return ns.EventType.Scan(value) -} - -// Value implements the driver Valuer interface. -func (ns NullEventType) Value() (driver.Value, error) { - if !ns.Valid { - return nil, nil - } - return string(ns.EventType), nil -} - -type Origin string - -const ( - OriginIngress Origin = "ingress" - OriginCron Origin = "cron" - OriginPubsub Origin = "pubsub" -) - -func (e *Origin) Scan(src interface{}) error { - switch s := src.(type) { - case []byte: - *e = Origin(s) - case string: - *e = Origin(s) - default: - return fmt.Errorf("unsupported scan type for Origin: %T", src) - } - return nil -} - -type NullOrigin struct { - Origin Origin - Valid bool // Valid is true if Origin is not NULL -} - -// Scan implements the Scanner interface. -func (ns *NullOrigin) Scan(value interface{}) error { - if value == nil { - ns.Origin, ns.Valid = "", false - return nil - } - ns.Valid = true - return ns.Origin.Scan(value) -} - -// Value implements the driver Valuer interface. -func (ns NullOrigin) Value() (driver.Value, error) { - if !ns.Valid { - return nil, nil - } - return string(ns.Origin), nil -} - -type RunnerState string - -const ( - RunnerStateIdle RunnerState = "idle" - RunnerStateReserved RunnerState = "reserved" - RunnerStateAssigned RunnerState = "assigned" - RunnerStateDead RunnerState = "dead" -) - -func (e *RunnerState) Scan(src interface{}) error { - switch s := src.(type) { - case []byte: - *e = RunnerState(s) - case string: - *e = RunnerState(s) - default: - return fmt.Errorf("unsupported scan type for RunnerState: %T", src) - } - return nil -} - -type NullRunnerState struct { - RunnerState RunnerState - Valid bool // Valid is true if RunnerState is not NULL -} - -// Scan implements the Scanner interface. -func (ns *NullRunnerState) Scan(value interface{}) error { - if value == nil { - ns.RunnerState, ns.Valid = "", false - return nil - } - ns.Valid = true - return ns.RunnerState.Scan(value) -} - -// Value implements the driver Valuer interface. -func (ns NullRunnerState) Value() (driver.Value, error) { - if !ns.Valid { - return nil, nil - } - return string(ns.RunnerState), nil -} - -type Artefact struct { - ID int64 - CreatedAt time.Time - Digest []byte - Content []byte -} - -type Controller struct { - ID int64 - Key model.ControllerKey - Created time.Time - LastSeen time.Time - State ControllerState - Endpoint string -} - -type Deployment struct { - ID int64 - CreatedAt time.Time - ModuleID int64 - Name model.DeploymentName - Schema *schema.Module - Labels []byte - MinReplicas int32 -} - -type DeploymentArtefact struct { - ArtefactID int64 - DeploymentID int64 - CreatedAt time.Time - Executable bool - Path string -} - -type Event struct { - ID int64 - TimeStamp time.Time - DeploymentID int64 - RequestID optional.Option[int64] - Type EventType - CustomKey1 optional.Option[string] - CustomKey2 optional.Option[string] - CustomKey3 optional.Option[string] - CustomKey4 optional.Option[string] - Payload json.RawMessage -} - -type IngressRoute struct { - Method string - Path string - DeploymentID int64 - Module string - Verb string -} - -type Module struct { - ID int64 - Language string - Name string -} - -type Request struct { - ID int64 - Origin Origin - Name string - SourceAddr string -} - -type Runner struct { - ID int64 - Key model.RunnerKey - Created time.Time - LastSeen time.Time - ReservationTimeout NullTime - State RunnerState - Endpoint string - ModuleName optional.Option[string] - DeploymentID optional.Option[int64] - Labels []byte -} diff --git a/backend/controller/sql/queries.sql.go b/backend/controller/sql/queries.sql.go deleted file mode 100644 index 073a0c3ba8..0000000000 --- a/backend/controller/sql/queries.sql.go +++ /dev/null @@ -1,1365 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.25.0 -// source: queries.sql - -package sql - -import ( - "context" - "encoding/json" - "time" - - "github.com/TBD54566975/ftl/backend/schema" - "github.com/TBD54566975/ftl/internal/model" - "github.com/alecthomas/types/optional" -) - -const associateArtefactWithDeployment = `-- name: AssociateArtefactWithDeployment :exec -INSERT INTO deployment_artefacts (deployment_id, artefact_id, executable, path) -VALUES ((SELECT id FROM deployments WHERE name = $1), $2, $3, $4) -` - -type AssociateArtefactWithDeploymentParams struct { - Name model.DeploymentName - ArtefactID int64 - Executable bool - Path string -} - -func (q *Queries) AssociateArtefactWithDeployment(ctx context.Context, arg AssociateArtefactWithDeploymentParams) error { - _, err := q.db.Exec(ctx, associateArtefactWithDeployment, - arg.Name, - arg.ArtefactID, - arg.Executable, - arg.Path, - ) - return err -} - -const createArtefact = `-- name: CreateArtefact :one -INSERT INTO artefacts (digest, content) -VALUES ($1, $2) -RETURNING id -` - -// Create a new artefact and return the artefact ID. -func (q *Queries) CreateArtefact(ctx context.Context, digest []byte, content []byte) (int64, error) { - row := q.db.QueryRow(ctx, createArtefact, digest, content) - var id int64 - err := row.Scan(&id) - return id, err -} - -const createDeployment = `-- name: CreateDeployment :exec -INSERT INTO deployments (module_id, "schema", name) -VALUES ((SELECT id FROM modules WHERE name = $2::TEXT LIMIT 1), $3::BYTEA, $1) -` - -func (q *Queries) CreateDeployment(ctx context.Context, name model.DeploymentName, moduleName string, schema []byte) error { - _, err := q.db.Exec(ctx, createDeployment, name, moduleName, schema) - return err -} - -const createIngressRequest = `-- name: CreateIngressRequest :exec -INSERT INTO requests (origin, name, source_addr) -VALUES ($1, $2, $3) -` - -func (q *Queries) CreateIngressRequest(ctx context.Context, origin Origin, name string, sourceAddr string) error { - _, err := q.db.Exec(ctx, createIngressRequest, origin, name, sourceAddr) - return err -} - -const createIngressRoute = `-- name: CreateIngressRoute :exec -INSERT INTO ingress_routes (deployment_id, module, verb, method, path) -VALUES ((SELECT id FROM deployments WHERE name = $1 LIMIT 1), $2, $3, $4, $5) -` - -type CreateIngressRouteParams struct { - Name model.DeploymentName - Module string - Verb string - Method string - Path string -} - -func (q *Queries) CreateIngressRoute(ctx context.Context, arg CreateIngressRouteParams) error { - _, err := q.db.Exec(ctx, createIngressRoute, - arg.Name, - arg.Module, - arg.Verb, - arg.Method, - arg.Path, - ) - return err -} - -const deregisterRunner = `-- name: DeregisterRunner :one -WITH matches AS ( - UPDATE runners - SET state = 'dead', - deployment_id = NULL - WHERE key = $1::runner_key - RETURNING 1) -SELECT COUNT(*) -FROM matches -` - -func (q *Queries) DeregisterRunner(ctx context.Context, key model.RunnerKey) (int64, error) { - row := q.db.QueryRow(ctx, deregisterRunner, key) - var count int64 - err := row.Scan(&count) - return count, err -} - -const expireRunnerReservations = `-- name: ExpireRunnerReservations :one -WITH rows AS ( - UPDATE runners - SET state = 'idle', - deployment_id = NULL, - reservation_timeout = NULL - WHERE state = 'reserved' - AND reservation_timeout < (NOW() AT TIME ZONE 'utc') - RETURNING 1) -SELECT COUNT(*) -FROM rows -` - -func (q *Queries) ExpireRunnerReservations(ctx context.Context) (int64, error) { - row := q.db.QueryRow(ctx, expireRunnerReservations) - var count int64 - err := row.Scan(&count) - return count, err -} - -const getActiveDeploymentSchemas = `-- name: GetActiveDeploymentSchemas :many -SELECT name, schema FROM deployments WHERE min_replicas > 0 -` - -type GetActiveDeploymentSchemasRow struct { - Name model.DeploymentName - Schema *schema.Module -} - -func (q *Queries) GetActiveDeploymentSchemas(ctx context.Context) ([]GetActiveDeploymentSchemasRow, error) { - rows, err := q.db.Query(ctx, getActiveDeploymentSchemas) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetActiveDeploymentSchemasRow - for rows.Next() { - var i GetActiveDeploymentSchemasRow - if err := rows.Scan(&i.Name, &i.Schema); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getActiveDeployments = `-- name: GetActiveDeployments :many -SELECT d.id, d.created_at, d.module_id, d.name, d.schema, d.labels, d.min_replicas, m.name AS module_name, m.language -FROM deployments d - INNER JOIN modules m on d.module_id = m.id -WHERE $1::bool = true - OR min_replicas > 0 -ORDER BY d.name -` - -type GetActiveDeploymentsRow struct { - Deployment Deployment - ModuleName string - Language string -} - -func (q *Queries) GetActiveDeployments(ctx context.Context, all bool) ([]GetActiveDeploymentsRow, error) { - rows, err := q.db.Query(ctx, getActiveDeployments, all) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetActiveDeploymentsRow - for rows.Next() { - var i GetActiveDeploymentsRow - if err := rows.Scan( - &i.Deployment.ID, - &i.Deployment.CreatedAt, - &i.Deployment.ModuleID, - &i.Deployment.Name, - &i.Deployment.Schema, - &i.Deployment.Labels, - &i.Deployment.MinReplicas, - &i.ModuleName, - &i.Language, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getActiveRunners = `-- name: GetActiveRunners :many -SELECT DISTINCT ON (r.key) r.key AS runner_key, - r.endpoint, - r.state, - r.labels, - r.last_seen, - r.module_name, - COALESCE(CASE - WHEN r.deployment_id IS NOT NULL - THEN d.name END, NULL) AS deployment_name -FROM runners r - LEFT JOIN deployments d on d.id = r.deployment_id -WHERE $1::bool = true - OR r.state <> 'dead' -ORDER BY r.key -` - -type GetActiveRunnersRow struct { - RunnerKey model.RunnerKey - Endpoint string - State RunnerState - Labels []byte - LastSeen time.Time - ModuleName optional.Option[string] - DeploymentName optional.Option[string] -} - -func (q *Queries) GetActiveRunners(ctx context.Context, all bool) ([]GetActiveRunnersRow, error) { - rows, err := q.db.Query(ctx, getActiveRunners, all) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetActiveRunnersRow - for rows.Next() { - var i GetActiveRunnersRow - if err := rows.Scan( - &i.RunnerKey, - &i.Endpoint, - &i.State, - &i.Labels, - &i.LastSeen, - &i.ModuleName, - &i.DeploymentName, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getAllIngressRoutes = `-- name: GetAllIngressRoutes :many -SELECT d.name AS deployment_name, ir.module, ir.verb, ir.method, ir.path -FROM ingress_routes ir - INNER JOIN deployments d ON ir.deployment_id = d.id -WHERE $1::bool = true - OR d.min_replicas > 0 -` - -type GetAllIngressRoutesRow struct { - DeploymentName model.DeploymentName - Module string - Verb string - Method string - Path string -} - -func (q *Queries) GetAllIngressRoutes(ctx context.Context, all bool) ([]GetAllIngressRoutesRow, error) { - rows, err := q.db.Query(ctx, getAllIngressRoutes, all) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetAllIngressRoutesRow - for rows.Next() { - var i GetAllIngressRoutesRow - if err := rows.Scan( - &i.DeploymentName, - &i.Module, - &i.Verb, - &i.Method, - &i.Path, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getArtefactContentRange = `-- name: GetArtefactContentRange :one -SELECT SUBSTRING(a.content FROM $1 FOR $2)::BYTEA AS content -FROM artefacts a -WHERE a.id = $3 -` - -func (q *Queries) GetArtefactContentRange(ctx context.Context, start int32, count int32, iD int64) ([]byte, error) { - row := q.db.QueryRow(ctx, getArtefactContentRange, start, count, iD) - var content []byte - err := row.Scan(&content) - return content, err -} - -const getArtefactDigests = `-- name: GetArtefactDigests :many -SELECT id, digest -FROM artefacts -WHERE digest = ANY ($1::bytea[]) -` - -type GetArtefactDigestsRow struct { - ID int64 - Digest []byte -} - -// Return the digests that exist in the database. -func (q *Queries) GetArtefactDigests(ctx context.Context, digests [][]byte) ([]GetArtefactDigestsRow, error) { - rows, err := q.db.Query(ctx, getArtefactDigests, digests) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetArtefactDigestsRow - for rows.Next() { - var i GetArtefactDigestsRow - if err := rows.Scan(&i.ID, &i.Digest); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getControllers = `-- name: GetControllers :many -SELECT id, key, created, last_seen, state, endpoint -FROM controller c -WHERE $1::bool = true - OR c.state <> 'dead' -ORDER BY c.key -` - -func (q *Queries) GetControllers(ctx context.Context, all bool) ([]Controller, error) { - rows, err := q.db.Query(ctx, getControllers, all) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Controller - for rows.Next() { - var i Controller - if err := rows.Scan( - &i.ID, - &i.Key, - &i.Created, - &i.LastSeen, - &i.State, - &i.Endpoint, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getDeployment = `-- name: GetDeployment :one -SELECT d.id, d.created_at, d.module_id, d.name, d.schema, d.labels, d.min_replicas, m.language, m.name AS module_name, d.min_replicas -FROM deployments d - INNER JOIN modules m ON m.id = d.module_id -WHERE d.name = $1 -` - -type GetDeploymentRow struct { - Deployment Deployment - Language string - ModuleName string - MinReplicas int32 -} - -func (q *Queries) GetDeployment(ctx context.Context, name model.DeploymentName) (GetDeploymentRow, error) { - row := q.db.QueryRow(ctx, getDeployment, name) - var i GetDeploymentRow - err := row.Scan( - &i.Deployment.ID, - &i.Deployment.CreatedAt, - &i.Deployment.ModuleID, - &i.Deployment.Name, - &i.Deployment.Schema, - &i.Deployment.Labels, - &i.Deployment.MinReplicas, - &i.Language, - &i.ModuleName, - &i.MinReplicas, - ) - return i, err -} - -const getDeploymentArtefacts = `-- name: GetDeploymentArtefacts :many -SELECT da.created_at, artefact_id AS id, executable, path, digest, executable -FROM deployment_artefacts da - INNER JOIN artefacts ON artefacts.id = da.artefact_id -WHERE deployment_id = $1 -` - -type GetDeploymentArtefactsRow struct { - CreatedAt time.Time - ID int64 - Executable bool - Path string - Digest []byte - Executable_2 bool -} - -// Get all artefacts matching the given digests. -func (q *Queries) GetDeploymentArtefacts(ctx context.Context, deploymentID int64) ([]GetDeploymentArtefactsRow, error) { - rows, err := q.db.Query(ctx, getDeploymentArtefacts, deploymentID) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetDeploymentArtefactsRow - for rows.Next() { - var i GetDeploymentArtefactsRow - if err := rows.Scan( - &i.CreatedAt, - &i.ID, - &i.Executable, - &i.Path, - &i.Digest, - &i.Executable_2, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getDeploymentsByID = `-- name: GetDeploymentsByID :many -SELECT id, created_at, module_id, name, schema, labels, min_replicas -FROM deployments -WHERE id = ANY ($1::BIGINT[]) -` - -func (q *Queries) GetDeploymentsByID(ctx context.Context, ids []int64) ([]Deployment, error) { - rows, err := q.db.Query(ctx, getDeploymentsByID, ids) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Deployment - for rows.Next() { - var i Deployment - if err := rows.Scan( - &i.ID, - &i.CreatedAt, - &i.ModuleID, - &i.Name, - &i.Schema, - &i.Labels, - &i.MinReplicas, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getDeploymentsNeedingReconciliation = `-- name: GetDeploymentsNeedingReconciliation :many -SELECT d.name AS deployment_name, - m.name AS module_name, - m.language AS language, - COUNT(r.id) AS assigned_runners_count, - d.min_replicas::BIGINT AS required_runners_count -FROM deployments d - LEFT JOIN runners r ON d.id = r.deployment_id AND r.state <> 'dead' - JOIN modules m ON d.module_id = m.id -GROUP BY d.name, d.min_replicas, m.name, m.language -HAVING COUNT(r.id) <> d.min_replicas -` - -type GetDeploymentsNeedingReconciliationRow struct { - DeploymentName model.DeploymentName - ModuleName string - Language string - AssignedRunnersCount int64 - RequiredRunnersCount int64 -} - -// Get deployments that have a mismatch between the number of assigned and required replicas. -func (q *Queries) GetDeploymentsNeedingReconciliation(ctx context.Context) ([]GetDeploymentsNeedingReconciliationRow, error) { - rows, err := q.db.Query(ctx, getDeploymentsNeedingReconciliation) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetDeploymentsNeedingReconciliationRow - for rows.Next() { - var i GetDeploymentsNeedingReconciliationRow - if err := rows.Scan( - &i.DeploymentName, - &i.ModuleName, - &i.Language, - &i.AssignedRunnersCount, - &i.RequiredRunnersCount, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getDeploymentsWithArtefacts = `-- name: GetDeploymentsWithArtefacts :many -SELECT d.id, d.created_at, d.name as deployment_name, d.schema, m.name AS module_name -FROM deployments d - INNER JOIN modules m ON d.module_id = m.id -WHERE EXISTS (SELECT 1 - FROM deployment_artefacts da - INNER JOIN artefacts a ON da.artefact_id = a.id - WHERE a.digest = ANY ($1::bytea[]) - AND da.deployment_id = d.id - AND d.schema = $2::BYTEA - HAVING COUNT(*) = $3::BIGINT -- Number of unique digests provided -) -` - -type GetDeploymentsWithArtefactsRow struct { - ID int64 - CreatedAt time.Time - DeploymentName model.DeploymentName - Schema *schema.Module - ModuleName string -} - -// Get all deployments that have artefacts matching the given digests. -func (q *Queries) GetDeploymentsWithArtefacts(ctx context.Context, digests [][]byte, schema []byte, count int64) ([]GetDeploymentsWithArtefactsRow, error) { - rows, err := q.db.Query(ctx, getDeploymentsWithArtefacts, digests, schema, count) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetDeploymentsWithArtefactsRow - for rows.Next() { - var i GetDeploymentsWithArtefactsRow - if err := rows.Scan( - &i.ID, - &i.CreatedAt, - &i.DeploymentName, - &i.Schema, - &i.ModuleName, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getExistingDeploymentForModule = `-- name: GetExistingDeploymentForModule :one -SELECT d.id, created_at, module_id, d.name, schema, labels, min_replicas, m.id, language, m.name -FROM deployments d - INNER JOIN modules m on d.module_id = m.id -WHERE m.name = $1 - AND min_replicas > 0 -LIMIT 1 -` - -type GetExistingDeploymentForModuleRow struct { - ID int64 - CreatedAt time.Time - ModuleID int64 - Name model.DeploymentName - Schema *schema.Module - Labels []byte - MinReplicas int32 - ID_2 int64 - Language string - Name_2 string -} - -func (q *Queries) GetExistingDeploymentForModule(ctx context.Context, name string) (GetExistingDeploymentForModuleRow, error) { - row := q.db.QueryRow(ctx, getExistingDeploymentForModule, name) - var i GetExistingDeploymentForModuleRow - err := row.Scan( - &i.ID, - &i.CreatedAt, - &i.ModuleID, - &i.Name, - &i.Schema, - &i.Labels, - &i.MinReplicas, - &i.ID_2, - &i.Language, - &i.Name_2, - ) - return i, err -} - -const getIdleRunners = `-- name: GetIdleRunners :many -SELECT id, key, created, last_seen, reservation_timeout, state, endpoint, module_name, deployment_id, labels -FROM runners -WHERE labels @> $1::jsonb - AND state = 'idle' -LIMIT $2 -` - -func (q *Queries) GetIdleRunners(ctx context.Context, labels []byte, limit int64) ([]Runner, error) { - rows, err := q.db.Query(ctx, getIdleRunners, labels, limit) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Runner - for rows.Next() { - var i Runner - if err := rows.Scan( - &i.ID, - &i.Key, - &i.Created, - &i.LastSeen, - &i.ReservationTimeout, - &i.State, - &i.Endpoint, - &i.ModuleName, - &i.DeploymentID, - &i.Labels, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getIngressRoutes = `-- name: GetIngressRoutes :many -SELECT r.key AS runner_key, d.name AS deployment_name, endpoint, ir.path, ir.module, ir.verb -FROM ingress_routes ir - INNER JOIN runners r ON ir.deployment_id = r.deployment_id - INNER JOIN deployments d ON ir.deployment_id = d.id -WHERE r.state = 'assigned' - AND ir.method = $1 -` - -type GetIngressRoutesRow struct { - RunnerKey model.RunnerKey - DeploymentName model.DeploymentName - Endpoint string - Path string - Module string - Verb string -} - -// Get the runner endpoints corresponding to the given ingress route. -func (q *Queries) GetIngressRoutes(ctx context.Context, method string) ([]GetIngressRoutesRow, error) { - rows, err := q.db.Query(ctx, getIngressRoutes, method) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetIngressRoutesRow - for rows.Next() { - var i GetIngressRoutesRow - if err := rows.Scan( - &i.RunnerKey, - &i.DeploymentName, - &i.Endpoint, - &i.Path, - &i.Module, - &i.Verb, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getModulesByID = `-- name: GetModulesByID :many -SELECT id, language, name -FROM modules -WHERE id = ANY ($1::BIGINT[]) -` - -func (q *Queries) GetModulesByID(ctx context.Context, ids []int64) ([]Module, error) { - rows, err := q.db.Query(ctx, getModulesByID, ids) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Module - for rows.Next() { - var i Module - if err := rows.Scan(&i.ID, &i.Language, &i.Name); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getProcessList = `-- name: GetProcessList :many -SELECT d.min_replicas, - d.name AS deployment_name, - d.labels deployment_labels, - r.key AS runner_key, - r.endpoint, - r.labels AS runner_labels -FROM deployments d - LEFT JOIN runners r on d.id = r.deployment_id AND r.state != 'dead' -WHERE d.min_replicas > 0 -ORDER BY d.name -` - -type GetProcessListRow struct { - MinReplicas int32 - DeploymentName model.DeploymentName - DeploymentLabels []byte - RunnerKey NullRunnerKey - Endpoint optional.Option[string] - RunnerLabels []byte -} - -func (q *Queries) GetProcessList(ctx context.Context) ([]GetProcessListRow, error) { - rows, err := q.db.Query(ctx, getProcessList) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetProcessListRow - for rows.Next() { - var i GetProcessListRow - if err := rows.Scan( - &i.MinReplicas, - &i.DeploymentName, - &i.DeploymentLabels, - &i.RunnerKey, - &i.Endpoint, - &i.RunnerLabels, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getRouteForRunner = `-- name: GetRouteForRunner :one -SELECT endpoint, r.key AS runner_key, r.module_name, d.name deployment_name, r.state -FROM runners r - LEFT JOIN deployments d on r.deployment_id = d.id -WHERE r.key = $1::runner_key -` - -type GetRouteForRunnerRow struct { - Endpoint string - RunnerKey model.RunnerKey - ModuleName optional.Option[string] - DeploymentName model.DeploymentName - State RunnerState -} - -// Retrieve routing information for a runner. -func (q *Queries) GetRouteForRunner(ctx context.Context, key model.RunnerKey) (GetRouteForRunnerRow, error) { - row := q.db.QueryRow(ctx, getRouteForRunner, key) - var i GetRouteForRunnerRow - err := row.Scan( - &i.Endpoint, - &i.RunnerKey, - &i.ModuleName, - &i.DeploymentName, - &i.State, - ) - return i, err -} - -const getRoutingTable = `-- name: GetRoutingTable :many -SELECT endpoint, r.key AS runner_key, r.module_name, d.name deployment_name -FROM runners r - LEFT JOIN deployments d on r.deployment_id = d.id -WHERE state = 'assigned' - AND (COALESCE(cardinality($1::TEXT[]), 0) = 0 - OR module_name = ANY ($1::TEXT[])) -` - -type GetRoutingTableRow struct { - Endpoint string - RunnerKey model.RunnerKey - ModuleName optional.Option[string] - DeploymentName model.DeploymentName -} - -func (q *Queries) GetRoutingTable(ctx context.Context, modules []string) ([]GetRoutingTableRow, error) { - rows, err := q.db.Query(ctx, getRoutingTable, modules) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetRoutingTableRow - for rows.Next() { - var i GetRoutingTableRow - if err := rows.Scan( - &i.Endpoint, - &i.RunnerKey, - &i.ModuleName, - &i.DeploymentName, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getRunner = `-- name: GetRunner :one -SELECT DISTINCT ON (r.key) r.key AS runner_key, - r.endpoint, - r.state, - r.labels, - r.last_seen, - r.module_name, - COALESCE(CASE - WHEN r.deployment_id IS NOT NULL - THEN d.name END, NULL) AS deployment_name -FROM runners r - LEFT JOIN deployments d on d.id = r.deployment_id OR r.deployment_id IS NULL -WHERE r.key = $1::runner_key -` - -type GetRunnerRow struct { - RunnerKey model.RunnerKey - Endpoint string - State RunnerState - Labels []byte - LastSeen time.Time - ModuleName optional.Option[string] - DeploymentName optional.Option[string] -} - -func (q *Queries) GetRunner(ctx context.Context, key model.RunnerKey) (GetRunnerRow, error) { - row := q.db.QueryRow(ctx, getRunner, key) - var i GetRunnerRow - err := row.Scan( - &i.RunnerKey, - &i.Endpoint, - &i.State, - &i.Labels, - &i.LastSeen, - &i.ModuleName, - &i.DeploymentName, - ) - return i, err -} - -const getRunnerState = `-- name: GetRunnerState :one -SELECT state -FROM runners -WHERE key = $1::runner_key -` - -func (q *Queries) GetRunnerState(ctx context.Context, key model.RunnerKey) (RunnerState, error) { - row := q.db.QueryRow(ctx, getRunnerState, key) - var state RunnerState - err := row.Scan(&state) - return state, err -} - -const getRunnersForDeployment = `-- name: GetRunnersForDeployment :many -SELECT r.id, key, created, last_seen, reservation_timeout, state, endpoint, module_name, deployment_id, r.labels, d.id, created_at, module_id, name, schema, d.labels, min_replicas -FROM runners r - INNER JOIN deployments d on r.deployment_id = d.id -WHERE state = 'assigned' - AND d.name = $1 -` - -type GetRunnersForDeploymentRow struct { - ID int64 - Key model.RunnerKey - Created time.Time - LastSeen time.Time - ReservationTimeout NullTime - State RunnerState - Endpoint string - ModuleName optional.Option[string] - DeploymentID optional.Option[int64] - Labels []byte - ID_2 int64 - CreatedAt time.Time - ModuleID int64 - Name model.DeploymentName - Schema *schema.Module - Labels_2 []byte - MinReplicas int32 -} - -func (q *Queries) GetRunnersForDeployment(ctx context.Context, name model.DeploymentName) ([]GetRunnersForDeploymentRow, error) { - rows, err := q.db.Query(ctx, getRunnersForDeployment, name) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetRunnersForDeploymentRow - for rows.Next() { - var i GetRunnersForDeploymentRow - if err := rows.Scan( - &i.ID, - &i.Key, - &i.Created, - &i.LastSeen, - &i.ReservationTimeout, - &i.State, - &i.Endpoint, - &i.ModuleName, - &i.DeploymentID, - &i.Labels, - &i.ID_2, - &i.CreatedAt, - &i.ModuleID, - &i.Name, - &i.Schema, - &i.Labels_2, - &i.MinReplicas, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const insertCallEvent = `-- name: InsertCallEvent :exec -INSERT INTO events (deployment_id, request_id, time_stamp, type, - custom_key_1, custom_key_2, custom_key_3, custom_key_4, payload) -VALUES ((SELECT id FROM deployments WHERE deployments.name = $1::TEXT), - (CASE - WHEN $2::TEXT IS NULL THEN NULL - ELSE (SELECT id FROM requests ir WHERE ir.name = $2::TEXT) - END), - $3::TIMESTAMPTZ, - 'call', - $4::TEXT, - $5::TEXT, - $6::TEXT, - $7::TEXT, - jsonb_build_object( - 'duration_ms', $8::BIGINT, - 'request', $9::JSONB, - 'response', $10::JSONB, - 'error', $11::TEXT, - 'stack', $12::TEXT - )) -` - -type InsertCallEventParams struct { - DeploymentName string - RequestName optional.Option[string] - TimeStamp time.Time - SourceModule optional.Option[string] - SourceVerb optional.Option[string] - DestModule string - DestVerb string - DurationMs int64 - Request []byte - Response []byte - Error optional.Option[string] - Stack optional.Option[string] -} - -func (q *Queries) InsertCallEvent(ctx context.Context, arg InsertCallEventParams) error { - _, err := q.db.Exec(ctx, insertCallEvent, - arg.DeploymentName, - arg.RequestName, - arg.TimeStamp, - arg.SourceModule, - arg.SourceVerb, - arg.DestModule, - arg.DestVerb, - arg.DurationMs, - arg.Request, - arg.Response, - arg.Error, - arg.Stack, - ) - return err -} - -const insertDeploymentCreatedEvent = `-- name: InsertDeploymentCreatedEvent :exec -INSERT INTO events (deployment_id, type, custom_key_1, custom_key_2, payload) -VALUES ((SELECT id - FROM deployments - WHERE deployments.name = $1::TEXT), - 'deployment_created', - $2::TEXT, - $3::TEXT, - jsonb_build_object( - 'min_replicas', $4::INT, - 'replaced', $5::TEXT - )) -` - -type InsertDeploymentCreatedEventParams struct { - DeploymentName string - Language string - ModuleName string - MinReplicas int32 - Replaced optional.Option[string] -} - -func (q *Queries) InsertDeploymentCreatedEvent(ctx context.Context, arg InsertDeploymentCreatedEventParams) error { - _, err := q.db.Exec(ctx, insertDeploymentCreatedEvent, - arg.DeploymentName, - arg.Language, - arg.ModuleName, - arg.MinReplicas, - arg.Replaced, - ) - return err -} - -const insertDeploymentUpdatedEvent = `-- name: InsertDeploymentUpdatedEvent :exec -INSERT INTO events (deployment_id, type, custom_key_1, custom_key_2, payload) -VALUES ((SELECT id - FROM deployments - WHERE deployments.name = $1::TEXT), - 'deployment_updated', - $2::TEXT, - $3::TEXT, - jsonb_build_object( - 'prev_min_replicas', $4::INT, - 'min_replicas', $5::INT - )) -` - -type InsertDeploymentUpdatedEventParams struct { - DeploymentName string - Language string - ModuleName string - PrevMinReplicas int32 - MinReplicas int32 -} - -func (q *Queries) InsertDeploymentUpdatedEvent(ctx context.Context, arg InsertDeploymentUpdatedEventParams) error { - _, err := q.db.Exec(ctx, insertDeploymentUpdatedEvent, - arg.DeploymentName, - arg.Language, - arg.ModuleName, - arg.PrevMinReplicas, - arg.MinReplicas, - ) - return err -} - -const insertEvent = `-- name: InsertEvent :exec -INSERT INTO events (deployment_id, request_id, type, - custom_key_1, custom_key_2, custom_key_3, custom_key_4, - payload) -VALUES ($1, $2, $3, $4, $5, $6, $7, $8) -RETURNING id -` - -type InsertEventParams struct { - DeploymentID int64 - RequestID optional.Option[int64] - Type EventType - CustomKey1 optional.Option[string] - CustomKey2 optional.Option[string] - CustomKey3 optional.Option[string] - CustomKey4 optional.Option[string] - Payload json.RawMessage -} - -func (q *Queries) InsertEvent(ctx context.Context, arg InsertEventParams) error { - _, err := q.db.Exec(ctx, insertEvent, - arg.DeploymentID, - arg.RequestID, - arg.Type, - arg.CustomKey1, - arg.CustomKey2, - arg.CustomKey3, - arg.CustomKey4, - arg.Payload, - ) - return err -} - -const insertLogEvent = `-- name: InsertLogEvent :exec -INSERT INTO events (deployment_id, request_id, time_stamp, custom_key_1, type, payload) -VALUES ((SELECT id FROM deployments d WHERE d.name = $1 LIMIT 1), - (CASE - WHEN $2::TEXT IS NULL THEN NULL - ELSE (SELECT id FROM requests ir WHERE ir.name = $2::TEXT LIMIT 1) - END), - $3::TIMESTAMPTZ, - $4::INT, - 'log', - jsonb_build_object( - 'message', $5::TEXT, - 'attributes', $6::JSONB, - 'error', $7::TEXT, - 'stack', $8::TEXT - )) -` - -type InsertLogEventParams struct { - DeploymentName model.DeploymentName - RequestName optional.Option[string] - TimeStamp time.Time - Level int32 - Message string - Attributes []byte - Error optional.Option[string] - Stack optional.Option[string] -} - -func (q *Queries) InsertLogEvent(ctx context.Context, arg InsertLogEventParams) error { - _, err := q.db.Exec(ctx, insertLogEvent, - arg.DeploymentName, - arg.RequestName, - arg.TimeStamp, - arg.Level, - arg.Message, - arg.Attributes, - arg.Error, - arg.Stack, - ) - return err -} - -const killStaleControllers = `-- name: KillStaleControllers :one -WITH matches AS ( - UPDATE controller - SET state = 'dead' - WHERE state <> 'dead' AND last_seen < (NOW() AT TIME ZONE 'utc') - $1::INTERVAL - RETURNING 1) -SELECT COUNT(*) -FROM matches -` - -// Mark any controller entries that haven't been updated recently as dead. -func (q *Queries) KillStaleControllers(ctx context.Context, timeout time.Duration) (int64, error) { - row := q.db.QueryRow(ctx, killStaleControllers, timeout) - var count int64 - err := row.Scan(&count) - return count, err -} - -const killStaleRunners = `-- name: KillStaleRunners :one -WITH matches AS ( - UPDATE runners - SET state = 'dead', - deployment_id = NULL - WHERE state <> 'dead' AND last_seen < (NOW() AT TIME ZONE 'utc') - $1::INTERVAL - RETURNING 1) -SELECT COUNT(*) -FROM matches -` - -func (q *Queries) KillStaleRunners(ctx context.Context, timeout time.Duration) (int64, error) { - row := q.db.QueryRow(ctx, killStaleRunners, timeout) - var count int64 - err := row.Scan(&count) - return count, err -} - -const replaceDeployment = `-- name: ReplaceDeployment :one -WITH update_container AS ( - UPDATE deployments AS d - SET min_replicas = update_deployments.min_replicas - FROM (VALUES ($1::TEXT, 0), - ($2::TEXT, $3::INT)) - AS update_deployments(name, min_replicas) - WHERE d.name = update_deployments.name - RETURNING 1) -SELECT COUNT(*) -FROM update_container -` - -func (q *Queries) ReplaceDeployment(ctx context.Context, oldDeployment string, newDeployment string, minReplicas int32) (int64, error) { - row := q.db.QueryRow(ctx, replaceDeployment, oldDeployment, newDeployment, minReplicas) - var count int64 - err := row.Scan(&count) - return count, err -} - -const reserveRunner = `-- name: ReserveRunner :one -UPDATE runners -SET state = 'reserved', - reservation_timeout = $1::timestamptz, - -- If a deployment is not found, then the deployment ID is -1 - -- and the update will fail due to a FK constraint. - deployment_id = COALESCE((SELECT id - FROM deployments d - WHERE d.name = $2 - LIMIT 1), -1) -WHERE id = (SELECT id - FROM runners r - WHERE r.state = 'idle' - AND r.labels @> $3::jsonb - LIMIT 1 FOR UPDATE SKIP LOCKED) -RETURNING runners.id, runners.key, runners.created, runners.last_seen, runners.reservation_timeout, runners.state, runners.endpoint, runners.module_name, runners.deployment_id, runners.labels -` - -// Find an idle runner and reserve it for the given deployment. -func (q *Queries) ReserveRunner(ctx context.Context, reservationTimeout time.Time, deploymentName model.DeploymentName, labels []byte) (Runner, error) { - row := q.db.QueryRow(ctx, reserveRunner, reservationTimeout, deploymentName, labels) - var i Runner - err := row.Scan( - &i.ID, - &i.Key, - &i.Created, - &i.LastSeen, - &i.ReservationTimeout, - &i.State, - &i.Endpoint, - &i.ModuleName, - &i.DeploymentID, - &i.Labels, - ) - return i, err -} - -const setDeploymentDesiredReplicas = `-- name: SetDeploymentDesiredReplicas :exec -UPDATE deployments -SET min_replicas = $2 -WHERE name = $1 -RETURNING 1 -` - -func (q *Queries) SetDeploymentDesiredReplicas(ctx context.Context, name model.DeploymentName, minReplicas int32) error { - _, err := q.db.Exec(ctx, setDeploymentDesiredReplicas, name, minReplicas) - return err -} - -const upsertController = `-- name: UpsertController :one -INSERT INTO controller (key, endpoint) -VALUES ($1, $2) -ON CONFLICT (key) DO UPDATE SET state = 'live', - endpoint = $2, - last_seen = NOW() AT TIME ZONE 'utc' -RETURNING id -` - -func (q *Queries) UpsertController(ctx context.Context, key model.ControllerKey, endpoint string) (int64, error) { - row := q.db.QueryRow(ctx, upsertController, key, endpoint) - var id int64 - err := row.Scan(&id) - return id, err -} - -const upsertModule = `-- name: UpsertModule :one -INSERT INTO modules (language, name) -VALUES ($1, $2) -ON CONFLICT (name) DO UPDATE SET language = $1 -RETURNING id -` - -func (q *Queries) UpsertModule(ctx context.Context, language string, name string) (int64, error) { - row := q.db.QueryRow(ctx, upsertModule, language, name) - var id int64 - err := row.Scan(&id) - return id, err -} - -const upsertRunner = `-- name: UpsertRunner :one -WITH deployment_rel AS ( - SELECT CASE - WHEN $5::TEXT IS NULL - THEN NULL - ELSE COALESCE((SELECT id - FROM deployments d - WHERE d.name = $5 - LIMIT 1), -1) END AS id) -INSERT -INTO runners (key, endpoint, state, labels, deployment_id, last_seen) -VALUES ($1, - $2, - $3, - $4, - (SELECT id FROM deployment_rel), - NOW() AT TIME ZONE 'utc') -ON CONFLICT (key) DO UPDATE SET endpoint = $2, - state = $3, - labels = $4, - deployment_id = (SELECT id FROM deployment_rel), - last_seen = NOW() AT TIME ZONE 'utc' -RETURNING deployment_id -` - -type UpsertRunnerParams struct { - Key model.RunnerKey - Endpoint string - State RunnerState - Labels []byte - DeploymentName optional.Option[string] -} - -// Upsert a runner and return the deployment ID that it is assigned to, if any. -// If the deployment name is null, then deployment_rel.id will be null, -// otherwise we try to retrieve the deployments.id using the key. If -// there is no corresponding deployment, then the deployment ID is -1 -// and the parent statement will fail due to a foreign key constraint. -func (q *Queries) UpsertRunner(ctx context.Context, arg UpsertRunnerParams) (optional.Option[int64], error) { - row := q.db.QueryRow(ctx, upsertRunner, - arg.Key, - arg.Endpoint, - arg.State, - arg.Labels, - arg.DeploymentName, - ) - var deployment_id optional.Option[int64] - err := row.Scan(&deployment_id) - return deployment_id, err -} diff --git a/backend/protos/xyz/block/ftl/v1/schema/schema.proto b/backend/protos/xyz/block/ftl/v1/schema/schema.proto deleted file mode 100644 index f46cf80241..0000000000 --- a/backend/protos/xyz/block/ftl/v1/schema/schema.proto +++ /dev/null @@ -1,245 +0,0 @@ -syntax = "proto3"; - -// This file is generated by github.com/TBD54566975/ftl/backend/schema/protobuf.go, DO NOT MODIFY -package xyz.block.ftl.v1.schema; - -import "xyz/block/ftl/v1/schema/runtime.proto"; - -option go_package = "github.com/TBD54566975/ftl/backend/protos/xyz/block/ftl/v1/schema;schemapb"; -option java_multiple_files = true; - -message Any { - optional Position pos = 1; -} - -message Array { - optional Position pos = 1; - Type element = 2; -} - -message Bool { - optional Position pos = 1; -} - -message Bytes { - optional Position pos = 1; -} - -message Config { - optional Position pos = 1; - string name = 2; - Type type = 3; -} - -message Data { - optional Position pos = 1; - repeated string comments = 2; - string name = 3; - repeated Field fields = 4; - repeated Metadata metadata = 5; - repeated TypeParameter typeParameters = 6; -} - -message Database { - optional Position pos = 1; - string name = 2; - repeated string comments = 3; -} - -message Decl { - oneof value { - Data data = 1; - Verb verb = 2; - Database database = 3; - Enum enum = 4; - Config config = 5; - Secret secret = 6; - } -} - -message Enum { - optional Position pos = 1; - repeated string comments = 2; - string name = 3; - Type type = 4; - repeated EnumVariant variants = 5; -} - -message EnumVariant { - optional Position pos = 1; - string name = 2; - Value value = 3; - repeated string comments = 4; -} - -message Field { - optional Position pos = 1; - string name = 2; - repeated string comments = 3; - Type type = 4; - repeated Metadata metadata = 5; -} - -message Float { - optional Position pos = 1; -} - -message IngressPathComponent { - oneof value { - IngressPathLiteral ingressPathLiteral = 1; - IngressPathParameter ingressPathParameter = 2; - } -} - -message IngressPathLiteral { - optional Position pos = 1; - string text = 2; -} - -message IngressPathParameter { - optional Position pos = 1; - string name = 2; -} - -message Int { - optional Position pos = 1; -} - -message IntValue { - optional Position pos = 1; - int64 value = 2; -} - -message Map { - optional Position pos = 1; - Type key = 2; - Type value = 3; -} - -message Metadata { - oneof value { - MetadataCalls calls = 1; - MetadataIngress ingress = 2; - MetadataDatabases databases = 3; - MetadataAlias alias = 4; - } -} - -message MetadataAlias { - optional Position pos = 1; - int64 kind = 2; - string alias = 3; -} - -message MetadataCalls { - optional Position pos = 1; - repeated Ref calls = 2; -} - -message MetadataDatabases { - optional Position pos = 1; - repeated Database calls = 2; -} - -message MetadataIngress { - optional Position pos = 1; - string type = 2; - string method = 3; - repeated IngressPathComponent path = 4; -} - -message Module { - optional ModuleRuntime runtime = 31634; - - optional Position pos = 1; - repeated string comments = 2; - bool builtin = 3; - string name = 4; - repeated Decl decls = 5; -} - -message Optional { - optional Position pos = 1; - optional Type type = 2; -} - -message Position { - string filename = 1; - int64 line = 2; - int64 column = 3; -} - -message Ref { - optional Position pos = 1; - string name = 2; - string module = 3; - repeated Type typeParameters = 4; -} - -message Schema { - optional Position pos = 1; - repeated Module modules = 2; -} - -message Secret { - optional Position pos = 1; - string name = 2; - Type type = 3; -} - -message String { - optional Position pos = 1; -} - -message StringValue { - optional Position pos = 1; - string value = 2; -} - -message Time { - optional Position pos = 1; -} - -message Type { - oneof value { - Int int = 1; - Float float = 2; - String string = 3; - Bytes bytes = 4; - Bool bool = 5; - Time time = 6; - Array array = 7; - Map map = 8; - Any any = 9; - Unit unit = 10; - Ref ref = 11; - Optional optional = 12; - } -} - -message TypeParameter { - optional Position pos = 1; - string name = 2; -} - -message Unit { - optional Position pos = 1; -} - -message Value { - oneof value { - StringValue stringValue = 1; - IntValue intValue = 2; - } -} - -message Verb { - optional VerbRuntime runtime = 31634; - - optional Position pos = 1; - string name = 2; - repeated string comments = 3; - Type request = 4; - Type response = 5; - repeated Metadata metadata = 6; -} diff --git a/internal/log/log_level_string.go b/internal/log/log_level_string.go deleted file mode 100644 index 4d53168cf4..0000000000 --- a/internal/log/log_level_string.go +++ /dev/null @@ -1,131 +0,0 @@ -// Code generated by "enumer -type=Level -text -transform=lower -output log_level_string.go"; DO NOT EDIT. - -package log - -import ( - "fmt" - "strings" -) - -const ( - _LevelName_0 = "defaulttrace" - _LevelLowerName_0 = "defaulttrace" - _LevelName_1 = "debug" - _LevelLowerName_1 = "debug" - _LevelName_2 = "info" - _LevelLowerName_2 = "info" - _LevelName_3 = "warn" - _LevelLowerName_3 = "warn" - _LevelName_4 = "error" - _LevelLowerName_4 = "error" -) - -var ( - _LevelIndex_0 = [...]uint8{0, 7, 12} - _LevelIndex_1 = [...]uint8{0, 5} - _LevelIndex_2 = [...]uint8{0, 4} - _LevelIndex_3 = [...]uint8{0, 4} - _LevelIndex_4 = [...]uint8{0, 5} -) - -func (i Level) String() string { - switch { - case 0 <= i && i <= 1: - return _LevelName_0[_LevelIndex_0[i]:_LevelIndex_0[i+1]] - case i == 5: - return _LevelName_1 - case i == 9: - return _LevelName_2 - case i == 13: - return _LevelName_3 - case i == 17: - return _LevelName_4 - default: - return fmt.Sprintf("Level(%d)", i) - } -} - -// An "invalid array index" compiler error signifies that the constant values have changed. -// Re-run the stringer command to generate them again. -func _LevelNoOp() { - var x [1]struct{} - _ = x[Default-(0)] - _ = x[Trace-(1)] - _ = x[Debug-(5)] - _ = x[Info-(9)] - _ = x[Warn-(13)] - _ = x[Error-(17)] -} - -var _LevelValues = []Level{Default, Trace, Debug, Info, Warn, Error} - -var _LevelNameToValueMap = map[string]Level{ - _LevelName_0[0:7]: Default, - _LevelLowerName_0[0:7]: Default, - _LevelName_0[7:12]: Trace, - _LevelLowerName_0[7:12]: Trace, - _LevelName_1[0:5]: Debug, - _LevelLowerName_1[0:5]: Debug, - _LevelName_2[0:4]: Info, - _LevelLowerName_2[0:4]: Info, - _LevelName_3[0:4]: Warn, - _LevelLowerName_3[0:4]: Warn, - _LevelName_4[0:5]: Error, - _LevelLowerName_4[0:5]: Error, -} - -var _LevelNames = []string{ - _LevelName_0[0:7], - _LevelName_0[7:12], - _LevelName_1[0:5], - _LevelName_2[0:4], - _LevelName_3[0:4], - _LevelName_4[0:5], -} - -// LevelString retrieves an enum value from the enum constants string name. -// Throws an error if the param is not part of the enum. -func LevelString(s string) (Level, error) { - if val, ok := _LevelNameToValueMap[s]; ok { - return val, nil - } - - if val, ok := _LevelNameToValueMap[strings.ToLower(s)]; ok { - return val, nil - } - return 0, fmt.Errorf("%s does not belong to Level values", s) -} - -// LevelValues returns all values of the enum -func LevelValues() []Level { - return _LevelValues -} - -// LevelStrings returns a slice of all String values of the enum -func LevelStrings() []string { - strs := make([]string, len(_LevelNames)) - copy(strs, _LevelNames) - return strs -} - -// IsALevel returns "true" if the value is listed in the enum definition. "false" otherwise -func (i Level) IsALevel() bool { - for _, v := range _LevelValues { - if i == v { - return true - } - } - return false -} - -// MarshalText implements the encoding.TextMarshaler interface for Level -func (i Level) MarshalText() ([]byte, error) { - return []byte(i.String()), nil -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface for Level -func (i *Level) UnmarshalText(text []byte) error { - var err error - *i, err = LevelString(string(text)) - return err -} diff --git a/kotlin-runtime/ftl-runtime/pom.xml b/kotlin-runtime/ftl-runtime/pom.xml index 284fac3d65..88767e69d9 100644 --- a/kotlin-runtime/ftl-runtime/pom.xml +++ b/kotlin-runtime/ftl-runtime/pom.xml @@ -1,27 +1,78 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - xyz.block - ftl - 1.0-SNAPSHOT - ../../pom.xml - - + xyz.block ftl-runtime jar + 1.0-SNAPSHOT + FTL + Towards a 𝝺-calculus for large-scale systems + https://github.com/TBD54566975/ftl + + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + - ${project.groupId}:${project.artifactId} + + + Alec Thomas + TBD + https://github.com/TBD54566975 + + + Wes Billman + TBD + https://github.com/TBD54566975 + + + Elizabeth Worstell + TBD + https://github.com/TBD54566975 + + + Matt Toohey + TBD + https://github.com/TBD54566975 + + + + + scm:git:git://github.com/TBD54566975/ftl.git + scm:git:ssh://github.com/TBD54566975/ftl.git + https://github.com/TBD54566975/ftl/tree/main + ${basedir}/../.. false 1.23.5 + 17 + 1.9.23 + false + 4.9.7 + 1.62.2 + 1.5.3 + 5.10.2 + 7.4 + + + + org.junit + junit-bom + ${junit.version} + pom + import + + + org.jetbrains.kotlin @@ -52,46 +103,59 @@ com.squareup.wire wire-runtime-jvm + ${wire.version} com.squareup.wire wire-grpc-server + ${wire.version} com.squareup.wire wire-grpc-client-jvm + ${wire.version} org.jetbrains.kotlin kotlin-stdlib + ${kotlin.version} + net.logstash.logback logstash-logback-encoder + ${logstash.version} ch.qos.logback logback-classic + ${logback.version} ch.qos.logback logback-core + ${logback.version} + io.grpc grpc-netty + ${grpc.version} io.grpc grpc-protobuf + ${grpc.version} io.grpc grpc-stub + ${grpc.version} org.hotswapagent hotswap-agent-core + 1.4.1 @@ -101,10 +165,26 @@ ${detekt.version} test + + org.jetbrains.kotlin + kotlin-test-junit5 + ${kotlin.version} + test + org.junit.jupiter junit-jupiter + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + org.junit-pioneer junit-pioneer @@ -120,6 +200,170 @@ + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.5.0 + + + generate-sources + + add-source + + + + ${project.basedir}/target/generated-sources/wire + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + Test* + *Test + + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.6.1 + + + initialize + + copy + + + + + com.squareup.wire + wire-compiler + ${wire.version} + jar-with-dependencies + wire-compiler.jar + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.2.0 + + + wire-client + initialize + + exec + + + java + + -jar + target/dependency/wire-compiler.jar + --proto_path=${rootDir}/backend/protos + + --kotlin_out=${project.build.directory}/generated-sources/wire + + --kotlin_rpc_role=client + + + + + wire-server + initialize + + exec + + + java + + -jar + target/dependency/wire-compiler.jar + --proto_path=${rootDir}/backend/protos + --kotlin_out=target/generated-sources/wire + --kotlin_rpc_role=server + --kotlin_rpc_call_style=blocking + --kotlin_grpc_server_compatible + --includes=xyz.block.ftl.v1.VerbService + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.2 + + + org.codehaus.mojo + flatten-maven-plugin + 1.6.0 + + + flatten + process-resources + + flatten + + + + flatten.clean + clean + + clean + + + + + + org.codehaus.mojo @@ -146,11 +390,117 @@ org.apache.maven.plugins maven-compiler-plugin + 3.12.1 - 11 - 11 + ${java.version} + ${java.version} + + + default-compile + none + + + + + + + release + + + + org.codehaus.mojo + flatten-maven-plugin + + ossrh + true + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.0 + + + attach-sources + package + + jar-no-fork + + + + + + org.jetbrains.dokka + dokka-maven-plugin + 1.9.20 + + + attach-javadoc + package + + javadocJar + + + + + + ${project.basedir}/src/main/kotlin + + ${project.build.directory} + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.1.0 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + --keyserver + hkp://keys.openpgp.org/ + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + true + + ${maven.deploy.skip} + ossrh + https://s01.oss.sonatype.org/ + true + 10 + + + + + + + + ossrh + https://s01.oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index c5bef3a7d0..0000000000 --- a/pom.xml +++ /dev/null @@ -1,441 +0,0 @@ - - - 4.0.0 - - xyz.block - ftl - 1.0-SNAPSHOT - pom - - FTL - Towards a 𝝺-calculus for large-scale systems - https://github.com/TBD54566975/ftl - - - - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - - Alec Thomas - TBD - https://github.com/TBD54566975 - - - Wes Billman - TBD - https://github.com/TBD54566975 - - - Elizabeth Worstell - TBD - https://github.com/TBD54566975 - - - - - scm:git:git://github.com/TBD54566975/ftl.git - scm:git:ssh://github.com/TBD54566975/ftl.git - https://github.com/TBD54566975/ftl/tree/main - - - - kotlin-runtime/ftl-runtime - - - - true - ${basedir} - 1.8 - 1.9.23 - false - 4.9.7 - 1.62.2 - 1.5.3 - 5.10.2 - 7.4 - - - - - - org.junit - junit-bom - ${junit.version} - pom - import - - - com.squareup.wire - wire-runtime-jvm - ${wire.version} - - - com.squareup.wire - wire-grpc-server - ${wire.version} - - - com.squareup.wire - wire-grpc-client-jvm - ${wire.version} - - - org.jetbrains.kotlin - kotlin-stdlib - ${kotlin.version} - - - - - net.logstash.logback - logstash-logback-encoder - ${logstash.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - ch.qos.logback - logback-core - ${logback.version} - - - - io.grpc - grpc-netty - ${grpc.version} - - - io.grpc - grpc-protobuf - ${grpc.version} - - - io.grpc - grpc-stub - ${grpc.version} - - - org.hotswapagent - hotswap-agent-core - 1.4.1 - - - - - - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.jetbrains.kotlin - kotlin-test-junit5 - ${kotlin.version} - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.junit-pioneer - junit-pioneer - 2.2.0 - test - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.12.1 - - - default-compile - none - - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 3.5.0 - - - generate-sources - - add-source - - - - ${project.basedir}/target/generated-sources/wire - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.2.5 - - - Test* - *Test - - - --add-opens java.base/java.util=ALL-UNNAMED - --add-opens java.base/java.lang=ALL-UNNAMED - - - - - kotlin-maven-plugin - org.jetbrains.kotlin - ${kotlin.version} - - - compile - - compile - - - - ${project.basedir}/src/main/kotlin - - - - - test-compile - - test-compile - - - - ${project.basedir}/src/test/kotlin - - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.6.1 - - - initialize - - copy - - - - - com.squareup.wire - wire-compiler - ${wire.version} - jar-with-dependencies - wire-compiler.jar - - - - - - - - - org.codehaus.mojo - exec-maven-plugin - 3.2.0 - - - wire-client - initialize - - exec - - - java - - -jar - target/dependency/wire-compiler.jar - --proto_path=${rootDir}/backend/protos - - --kotlin_out=${project.build.directory}/generated-sources/wire - - --kotlin_rpc_role=client - - - - - wire-server - initialize - - exec - - - java - - -jar - target/dependency/wire-compiler.jar - --proto_path=${rootDir}/backend/protos - --kotlin_out=target/generated-sources/wire - --kotlin_rpc_role=server - --kotlin_rpc_call_style=blocking - --kotlin_grpc_server_compatible - --includes=xyz.block.ftl.v1.VerbService - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.2 - - - org.codehaus.mojo - flatten-maven-plugin - 1.6.0 - - - flatten - process-resources - - flatten - - - - flatten.clean - clean - - clean - - - - - - - - - - - - release - - kotlin-runtime/ftl-runtime - - - - - org.codehaus.mojo - flatten-maven-plugin - - ossrh - true - - - - org.apache.maven.plugins - maven-source-plugin - 3.3.0 - - - attach-sources - package - - jar-no-fork - - - - - - org.jetbrains.dokka - dokka-maven-plugin - 1.9.20 - - - attach-javadoc - package - - javadocJar - - - - - - ${project.basedir}/src/main/kotlin - - ${project.build.directory} - - - - org.apache.maven.plugins - maven-gpg-plugin - 3.1.0 - - - sign-artifacts - verify - - sign - - - - --pinentry-mode - loopback - --keyserver - hkp://keys.openpgp.org/ - - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.13 - true - - ${maven.deploy.skip} - ossrh - https://s01.oss.sonatype.org/ - true - 10 - - - - - - - - ossrh - https://s01.oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - \ No newline at end of file