mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 19:17:10 +00:00
installs, builds and serves each implementation on its own port, then hands the campaign tool the same seed slice, step budget and generator for all of them, so a difference between implementations is not a difference in exploration. the generator and platform are fixed rather than exposed.
118 lines
3.9 KiB
Go
118 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
manifestFileName = "sweep.json"
|
|
recordsFileName = "implementations.jsonl"
|
|
seedPlaceholder = "{seed}"
|
|
)
|
|
|
|
// plannedImplementation is one implementation the sweep intends to run, with
|
|
// the port it is served on and the URL every seed is served at.
|
|
type plannedImplementation struct {
|
|
Name string `json:"name"`
|
|
Directory string `json:"directory"`
|
|
Port int `json:"port"`
|
|
URLTemplate string `json:"url_template"`
|
|
}
|
|
|
|
// manifest is sweep.json: what the sweep INTENDED to run, written before the
|
|
// first install so a host that dropped an implementation or a seed shows up as
|
|
// a missing run rather than as a smaller sample.
|
|
type manifest struct {
|
|
Generator string `json:"generator"`
|
|
Platform string `json:"platform"`
|
|
SpecPath string `json:"spec_path"`
|
|
MaxSteps int `json:"max_steps"`
|
|
DurationMillis int64 `json:"duration_millis"`
|
|
Seeds []int64 `json:"seeds"`
|
|
Implementations []plannedImplementation `json:"implementations"`
|
|
Concurrency int `json:"concurrency"`
|
|
Host string `json:"host"`
|
|
BunPath string `json:"bun_path"`
|
|
CampaignPath string `json:"campaign_path"`
|
|
SanderlingPath string `json:"sanderling_path"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
}
|
|
|
|
func buildManifest(
|
|
configuration config,
|
|
implementations []implementation,
|
|
host string,
|
|
startedAt time.Time,
|
|
) manifest {
|
|
planned := make([]plannedImplementation, 0, len(implementations))
|
|
for _, target := range implementations {
|
|
planned = append(planned, plannedImplementation{
|
|
Name: target.Name,
|
|
Directory: target.Directory,
|
|
Port: target.Port,
|
|
URLTemplate: servedURL(target.Port, seedPlaceholder),
|
|
})
|
|
}
|
|
return manifest{
|
|
Generator: generator,
|
|
Platform: platform,
|
|
SpecPath: configuration.specPath,
|
|
MaxSteps: configuration.maxSteps,
|
|
DurationMillis: configuration.duration.Milliseconds(),
|
|
Seeds: configuration.seeds,
|
|
Implementations: planned,
|
|
Concurrency: configuration.concurrency,
|
|
Host: host,
|
|
BunPath: configuration.bunPath,
|
|
CampaignPath: configuration.campaignPath,
|
|
SanderlingPath: configuration.sanderlingPath,
|
|
StartedAt: startedAt,
|
|
}
|
|
}
|
|
|
|
func writeManifest(directory string, value manifest) error {
|
|
body, err := json.MarshalIndent(value, "", " ")
|
|
if err != nil {
|
|
return fmt.Errorf("marshal manifest: %w", err)
|
|
}
|
|
return os.WriteFile(
|
|
filepath.Join(directory, manifestFileName),
|
|
append(body, '\n'),
|
|
0o644,
|
|
)
|
|
}
|
|
|
|
// runRecord is one campaign, which is one implementation at one seed.
|
|
type runRecord struct {
|
|
Seed int64 `json:"seed"`
|
|
URL string `json:"url"`
|
|
ExitCode int `json:"exit_code"`
|
|
LaunchError string `json:"launch_error,omitempty"`
|
|
CampaignDirectory string `json:"campaign_directory"`
|
|
MonotonicMillis int64 `json:"monotonic_millis"`
|
|
}
|
|
|
|
// implementationRecord is one line of implementations.jsonl. FailedStage names
|
|
// the step that stopped this implementation, and an implementation that never
|
|
// got past install, build or serve carries no runs at all.
|
|
type implementationRecord struct {
|
|
Name string `json:"implementation"`
|
|
Directory string `json:"directory"`
|
|
Port int `json:"port"`
|
|
FailedStage string `json:"failed_stage,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
MonotonicMillis int64 `json:"monotonic_millis"`
|
|
Runs []runRecord `json:"runs"`
|
|
}
|
|
|
|
const (
|
|
stageInstall = "install"
|
|
stageBuild = "build"
|
|
stageServe = "serve"
|
|
)
|