init
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
// Package runner orchestrates the once-a-day simulation against the store.
|
||||
package runner
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"wh/config"
|
||||
"wh/sim"
|
||||
"wh/store"
|
||||
)
|
||||
|
||||
const (
|
||||
MetaConfig = "config"
|
||||
MetaDay = "day"
|
||||
MetaMarket = "market"
|
||||
)
|
||||
|
||||
// RunNextDay simulates the next day atomically: everything is committed
|
||||
// together or not at all, so a crashed run can simply be repeated.
|
||||
func RunNextDay(ctx context.Context, s *store.Store, cfg config.Config) (sim.DayResult, error) {
|
||||
var res sim.DayResult
|
||||
cfgJSON, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
err = s.WithTx(ctx, func(q *store.Q) error {
|
||||
if err := q.LockWorld(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
// Refuse to continue a world with different parameters.
|
||||
if prev, ok, err := q.GetMeta(ctx, MetaConfig); err != nil {
|
||||
return err
|
||||
} else if ok && prev != string(cfgJSON) {
|
||||
return fmt.Errorf("config differs from the one this world was created with:\n stored: %s\n current: %s", prev, cfgJSON)
|
||||
}
|
||||
|
||||
st, err := q.LoadState(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if st == nil {
|
||||
st = sim.NewState(cfg)
|
||||
if err := q.SetMeta(ctx, MetaConfig, string(cfgJSON)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := q.SaveState(ctx, st); err != nil { // day 0 snapshot
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var in sim.DayInput
|
||||
if in.Launches, err = q.PendingLaunches(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Uplinks, err = q.PendingUplinks(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if res, err = st.RunDay(cfg, in); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := q.SaveState(ctx, st); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := q.RecordRun(ctx, res, time.Now().UTC().Format(time.RFC3339)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := q.AfterRun(ctx, st); err != nil {
|
||||
return err
|
||||
}
|
||||
mk, _ := json.Marshal(st.Market.Prices)
|
||||
if err := q.SetMeta(ctx, MetaMarket, string(mk)); err != nil {
|
||||
return err
|
||||
}
|
||||
return q.SetMeta(ctx, MetaDay, fmt.Sprint(st.Day))
|
||||
})
|
||||
return res, err
|
||||
}
|
||||
Reference in New Issue
Block a user