Skip to content

Commit

Permalink
fly deploy: concurrently acquire/release leases, update flaps.Wait() …
Browse files Browse the repository at this point in the history
…to better handle timeouts
  • Loading branch information
tvdfly authored and dangra committed Jan 25, 2023
1 parent cd586b7 commit d484353
Show file tree
Hide file tree
Showing 5 changed files with 331 additions and 99 deletions.
21 changes: 14 additions & 7 deletions api/machine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (
)

const MachineConfigMetadataKeyFlyPlatformVersion = "fly_platform_version"
const MachineConfigMetadataKeyFlyRelease = "fly_release"
const MachineConfigMetadataKeyFlyReleaseId = "fly_release_id"
const MachineConfigMetadataKeyFlyReleaseVersion = "fly_release_version"
const MachineFlyPlatformVersion2 = "v2"
const MachineProcessGroupApp = "app"
const MachineProcessGroupReleaseCommand = "release_command"
const MachineStateDestroyed = "destroyed"
const MachineStateStarted = "started"
const MachineStateStopped = "stopped"

type Machine struct {
ID string `json:"id"`
Expand Down Expand Up @@ -236,12 +239,16 @@ type DNSConfig struct {
}

type MachineLease struct {
Status string `json:"status"`
Data struct {
Nonce string `json:"nonce"`
ExpiresAt int64 `json:"expires_at"`
Owner string `json:"owner"`
}
Status string `json:"status"`
Data *MachineLeaseData `json:"data,omitempty"`
Message string `json:"message,omitempty"`
Code string `json:"code,omitempty"`
}

type MachineLeaseData struct {
Nonce string `json:"nonce"`
ExpiresAt int64 `json:"expires_at"`
Owner string `json:"owner"`
}

type MachineStartResponse struct {
Expand Down
42 changes: 29 additions & 13 deletions flaps/flaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"net"
"net/http"
"strings"
"time"

"github.com/google/go-querystring/query"
"github.com/samber/lo"

"github.com/superfly/flyctl/agent"
Expand Down Expand Up @@ -119,26 +121,40 @@ func (f *Client) Start(ctx context.Context, machineID string) (*api.MachineStart
return out, nil
}

func (f *Client) Wait(ctx context.Context, machine *api.Machine, state string) (err error) {
waitEndpoint := fmt.Sprintf("/%s/wait", machine.ID)
type waitQuerystring struct {
InstanceId string `url:"instance_id,omitempty"`
TimeoutSeconds int `url:"timeout,omitempty"`
State string `url:"state,omitempty"`
}

version := machine.InstanceID
const proxyTimeoutThreshold = 60 * time.Second

func (f *Client) Wait(ctx context.Context, machine *api.Machine, state string, timeout time.Duration) (err error) {
waitEndpoint := fmt.Sprintf("/%s/wait", machine.ID)
if state == "" {
state = "started"
}
version := machine.InstanceID
if machine.Version != "" {
version = machine.Version
}
if version != "" {
waitEndpoint += fmt.Sprintf("?instance_id=%s&timeout=30", version)
} else {
waitEndpoint += "?timeout=30"
if timeout > proxyTimeoutThreshold {
timeout = proxyTimeoutThreshold
}

if state == "" {
state = "started"
if timeout < 1*time.Second {
timeout = 1 * time.Second
}

waitEndpoint += fmt.Sprintf("&state=%s", state)

timeoutSeconds := int(timeout.Seconds())
waitQs := waitQuerystring{
InstanceId: version,
TimeoutSeconds: timeoutSeconds,
State: state,
}
qsVals, err := query.Values(waitQs)
if err != nil {
return fmt.Errorf("error making query string for wait request: %w", err)
}
waitEndpoint += fmt.Sprintf("?%s", qsVals.Encode())
if err := f.sendRequest(ctx, http.MethodGet, waitEndpoint, nil, nil, nil); err != nil {
return fmt.Errorf("failed to wait for VM %s in %s state: %w", machine.ID, state, err)
}
Expand Down

0 comments on commit d484353

Please sign in to comment.