#Quick idea on slightly modified go sdk

1 messages · Page 1 of 1 (latest)

solemn pumice
#
package main

import (
    "context"
    "fmt"
    "strings"
)

func main() {
    dag.Environment().
        WithCommand(PublishAll{}).
        WithCheck(UnitTest{}).
        WithCheck(IntegTest{}).
        WithShell(Dev{}).
        Serve()
}

type PublishAll struct {
    // The version of the server and client to publish
    Version string
}

func (p *PublishAll) Command(ctx context.Context) (string, error) {
    // First, publish the server
    serverOutput, err := dag.DemoServer().Publish(ctx, version)
    if err != nil {
        return "", fmt.Errorf("failed to publish go server: %w", err)
    }

    // if that worked, publish the client app
    clientOutput, err := dag.DemoClient().Publish(ctx, version)
    if err != nil {
        return "", fmt.Errorf("failed to publish python app: %w", err)
    }

    return strings.Join([]string{serverOutput, clientOutput}, "\n"), nil
}

func (p *PublishAll) Defaults() {
    p.Version = "latest"
}

type UnitTest struct{}

func (UnitTest) Check(ctx context.Context) (*EnvironmentCheckResult, error) {
    return dag.EnvironmentCheck().
        WithSubcheck(dag.DemoClient().UnitTest()).
        WithSubcheck(dag.DemoServer().UnitTest()).Result(), nil
}

type Dev struct{}

func (Dev) Shell(ctx context.Context) (*Container, error) {
    clientApp := dag.DemoClient().ClientImage().Container()

    return clientApp.
        WithServiceBinding("server", dag.DemoServer().ServerImage().Container()).
        WithEntrypoint([]string{"sh"}), nil
}

type IntegTest struct{}

func (IntegTest) Check(ctx context.Context) (*EnvironmentCheckResult, error) {
    clientApp := dag.DemoClient().ClientImage().Container()

    stdout, err := clientApp.
        WithServiceBinding("server", dag.DemoServer().ServerImage().Container()).
        WithExec(nil).
        Stdout(ctx)
    if err != nil {
        return dag.EnvironmentCheckResult().WithOutput(err.Error()), nil
    }
    return dag.EnvironmentCheckResult().WithSuccess(true).WithOutput(stdout), nil
}
#

The improvements are:

  1. Parameters (for the entrypoints that support them) are now struct fields, which makes it very obvious + intuitive how to add doc strings to them without resorting to hacks where we attempt to parse //comments above funcs and extract parameter-specific doc strings (go has no built-in support for that, but it does have built-in support for comments on struct fields)
  2. A potentially nice+simple route to supporting default values in go (see the Defaults() method attached to PublishAll)
  3. The env With* methods no longer have to accept type any, which I have a fear could become a huge annoyance in the long run since it removes type safety from that part of the code. Instead they accept interface { ... } definitions and users get nice IDE errors if they do something wrong

Downsides:

  1. A little bit more verbose than just straight up funcs
  2. Accepting an interface rather than any does sacrifice a bit of polymorphism (i.e. we can't make error optional anymore), so that's a tradeoff rather than total improvement

Obviously we have way more on our plate so I'm not going to pursue this unless others think it's just clearly far and away better than the current state, but if you have any opinion beyond "meh" let me know @lunar pagoda @bright gust

#

I guess also, WithFunction will still have to accept any, no way of avoiding that

lunar pagoda
#

Interesting, I like some of the upside but personally prefer the current mode, it's really satisfying when you're able to chain together a bunch of client calls and not have an error return value. Feels more like scripting/composition