@@ -6,10 +6,8 @@ import (
66 "database/sql"
77 "embed"
88 "encoding/hex"
9- "encoding/json"
109 "errors"
1110 "fmt"
12- "io"
1311 "os"
1412 "path/filepath"
1513 "strings"
@@ -29,12 +27,6 @@ const (
2927//go:embed migrations/*.sql
3028var migrationsFS embed.FS
3129
32- type legacyPersistentState struct {
33- Runs []Run `json:"runs"`
34- Tasks []Task `json:"tasks"`
35- Deliveries map [string ]time.Time `json:"deliveries"`
36- }
37-
3830type Store struct {
3931 mu sync.RWMutex
4032 path string
@@ -54,20 +46,6 @@ func New(path string, maxRuns int) (*Store, error) {
5446 return nil , fmt .Errorf ("create state directory: %w" , err )
5547 }
5648
57- legacy , hasLegacy , err := detectLegacyState (path )
58- if err != nil {
59- return nil , err
60- }
61- if hasLegacy {
62- backup := path + ".legacy.json"
63- if _ , statErr := os .Stat (backup ); statErr == nil {
64- backup = fmt .Sprintf ("%s.%d" , backup , time .Now ().UTC ().Unix ())
65- }
66- if err := os .Rename (path , backup ); err != nil {
67- return nil , fmt .Errorf ("backup legacy state: %w" , err )
68- }
69- }
70-
7149 db , err := sql .Open (sqliteDriverName , path )
7250 if err != nil {
7351 return nil , fmt .Errorf ("open sqlite: %w" , err )
@@ -101,12 +79,6 @@ func New(path string, maxRuns int) (*Store, error) {
10179 db : db ,
10280 q : sqlitegen .New (db ),
10381 }
104- if hasLegacy {
105- if err := s .importLegacy (legacy ); err != nil {
106- _ = db .Close ()
107- return nil , fmt .Errorf ("import legacy state: %w" , err )
108- }
109- }
11082 return s , nil
11183}
11284
@@ -494,170 +466,6 @@ func (s *Store) RecordDelivery(deliveryID string) error {
494466 return s .q .DeleteOldestDeliveries (context .Background (), count - maxDeliveries )
495467}
496468
497- func detectLegacyState (path string ) (* legacyPersistentState , bool , error ) {
498- f , err := os .Open (path )
499- if err != nil {
500- if os .IsNotExist (err ) {
501- return nil , false , nil
502- }
503- return nil , false , fmt .Errorf ("open state file: %w" , err )
504- }
505- defer f .Close ()
506-
507- sample := make ([]byte , 512 )
508- n , _ := f .Read (sample )
509- head := strings .TrimSpace (string (sample [:n ]))
510- if head == "" {
511- return nil , false , nil
512- }
513- if ! strings .HasPrefix (head , "{" ) {
514- return nil , false , nil
515- }
516- if _ , err := f .Seek (0 , io .SeekStart ); err != nil {
517- return nil , false , fmt .Errorf ("seek state file: %w" , err )
518- }
519- var legacy legacyPersistentState
520- if err := json .NewDecoder (f ).Decode (& legacy ); err != nil {
521- return nil , false , fmt .Errorf ("decode legacy state file: %w" , err )
522- }
523- return & legacy , true , nil
524- }
525-
526- func (s * Store ) importLegacy (legacy * legacyPersistentState ) error {
527- if legacy == nil {
528- return nil
529- }
530- tx , err := s .db .BeginTx (context .Background (), nil )
531- if err != nil {
532- return err
533- }
534- defer tx .Rollback ()
535- qtx := s .q .WithTx (tx )
536-
537- for _ , t := range legacy .Tasks {
538- created := t .CreatedAt .UnixNano ()
539- if t .CreatedAt .IsZero () {
540- created = time .Now ().UTC ().UnixNano ()
541- }
542- updated := t .UpdatedAt .UnixNano ()
543- if t .UpdatedAt .IsZero () {
544- updated = created
545- }
546- if _ , err := qtx .UpsertTask (context .Background (), sqlitegen.UpsertTaskParams {
547- ID : t .ID ,
548- Repo : t .Repo ,
549- IssueNumber : int64 (t .IssueNumber ),
550- PrNumber : int64 (t .PRNumber ),
551- Status : string (TaskOpen ),
552- PendingInput : false ,
553- LastRunID : "" ,
554- CreatedAt : created ,
555- UpdatedAt : updated ,
556- }); err != nil {
557- return err
558- }
559- if _ , err := qtx .SetTaskPendingInput (context .Background (), sqlitegen.SetTaskPendingInputParams {
560- PendingInput : t .PendingInput ,
561- UpdatedAt : updated ,
562- ID : t .ID ,
563- }); err != nil {
564- return err
565- }
566- if _ , err := qtx .SetTaskLastRun (context .Background (), sqlitegen.SetTaskLastRunParams {
567- LastRunID : t .LastRunID ,
568- UpdatedAt : updated ,
569- IssueNumber : int64 (t .IssueNumber ),
570- PrNumber : int64 (t .PRNumber ),
571- ID : t .ID ,
572- }); err != nil {
573- return err
574- }
575- if t .Status == TaskCompleted {
576- if _ , err := qtx .MarkTaskCompleted (context .Background (), sqlitegen.MarkTaskCompletedParams {UpdatedAt : updated , ID : t .ID }); err != nil {
577- return err
578- }
579- }
580- }
581-
582- for i := len (legacy .Runs ) - 1 ; i >= 0 ; i -- {
583- r := legacy .Runs [i ]
584- if _ , err := qtx .UpsertTask (context .Background (), sqlitegen.UpsertTaskParams {
585- ID : r .TaskID ,
586- Repo : r .Repo ,
587- IssueNumber : int64 (r .IssueNumber ),
588- PrNumber : int64 (r .PRNumber ),
589- Status : string (TaskOpen ),
590- PendingInput : false ,
591- LastRunID : "" ,
592- CreatedAt : fallbackUnixNano (r .CreatedAt , time .Now ().UTC ()),
593- UpdatedAt : fallbackUnixNano (r .UpdatedAt , r .CreatedAt ),
594- }); err != nil {
595- return err
596- }
597- if _ , err := qtx .InsertRun (context .Background (), sqlitegen.InsertRunParams {
598- ID : r .ID ,
599- TaskID : r .TaskID ,
600- Repo : r .Repo ,
601- Task : r .Task ,
602- BaseBranch : r .BaseBranch ,
603- HeadBranch : r .HeadBranch ,
604- Trigger : r .Trigger ,
605- Debug : r .Debug ,
606- Status : string (r .Status ),
607- RunDir : r .RunDir ,
608- IssueNumber : int64 (r .IssueNumber ),
609- PrNumber : int64 (r .PRNumber ),
610- PrUrl : r .PRURL ,
611- HeadSha : r .HeadSHA ,
612- Context : r .Context ,
613- Error : r .Error ,
614- CreatedAt : fallbackUnixNano (r .CreatedAt , time .Now ().UTC ()),
615- UpdatedAt : fallbackUnixNano (r .UpdatedAt , r .CreatedAt ),
616- StartedAt : toNullInt64 (r .StartedAt ),
617- CompletedAt : toNullInt64 (r .CompletedAt ),
618- }); err != nil {
619- if strings .Contains (err .Error (), "UNIQUE constraint failed: runs.id" ) {
620- continue
621- }
622- return err
623- }
624- if _ , err := qtx .SetTaskLastRun (context .Background (), sqlitegen.SetTaskLastRunParams {
625- LastRunID : r .ID ,
626- UpdatedAt : fallbackUnixNano (r .UpdatedAt , r .CreatedAt ),
627- IssueNumber : int64 (r .IssueNumber ),
628- PrNumber : int64 (r .PRNumber ),
629- ID : r .TaskID ,
630- }); err != nil {
631- return err
632- }
633- }
634-
635- for id , ts := range legacy .Deliveries {
636- if err := qtx .RecordDelivery (context .Background (), sqlitegen.RecordDeliveryParams {
637- ID : id ,
638- SeenAt : fallbackUnixNano (ts , time .Now ().UTC ()),
639- }); err != nil {
640- return err
641- }
642- }
643-
644- if err := qtx .TrimOldRuns (context .Background (), int64 (s .maxRuns )); err != nil {
645- return err
646- }
647-
648- count , err := qtx .CountDeliveries (context .Background ())
649- if err != nil {
650- return err
651- }
652- if count > maxDeliveries {
653- if err := qtx .DeleteOldestDeliveries (context .Background (), count - maxDeliveries ); err != nil {
654- return err
655- }
656- }
657-
658- return tx .Commit ()
659- }
660-
661469func fromDBTask (t sqlitegen.Task ) Task {
662470 return Task {
663471 ID : t .ID ,
0 commit comments