github.com/drone/runner-go@v1.12.0/pipeline/reporter/history/history.go (about) 1 // Copyright 2019 Drone.IO Inc. All rights reserved. 2 // Use of this source code is governed by the Polyform License 3 // that can be found in the LICENSE file. 4 5 // Package history implements a tracer that provides access to 6 // pipeline execution history. 7 package history 8 9 import ( 10 "context" 11 "sync" 12 "time" 13 14 "github.com/drone/runner-go/internal" 15 "github.com/drone/runner-go/pipeline" 16 ) 17 18 var _ pipeline.Reporter = (*History)(nil) 19 20 // default number of historical entries. 21 const defaultLimit = 25 22 23 // History tracks pending, running and complete pipeline stages 24 // processed by the system. 25 type History struct { 26 sync.Mutex 27 base pipeline.Reporter 28 limit int 29 items []*Entry 30 } 31 32 // New returns a new History recorder that wraps the base 33 // reporter. 34 func New(base pipeline.Reporter) *History { 35 return &History{base: base} 36 } 37 38 // ReportStage adds or updates the pipeline history. 39 func (h *History) ReportStage(ctx context.Context, state *pipeline.State) error { 40 h.Lock() 41 h.update(state) 42 h.prune() 43 h.Unlock() 44 return h.base.ReportStage(ctx, state) 45 } 46 47 // ReportStep adds or updates the pipeline history. 48 func (h *History) ReportStep(ctx context.Context, state *pipeline.State, name string) error { 49 h.Lock() 50 h.update(state) 51 h.prune() 52 h.Unlock() 53 return h.base.ReportStep(ctx, state, name) 54 } 55 56 // Entries returns a list of entries. 57 func (h *History) Entries() []*Entry { 58 h.Lock() 59 var entries []*Entry 60 for _, src := range h.items { 61 dst := new(Entry) 62 *dst = *src 63 entries = append(entries, dst) 64 } 65 h.Unlock() 66 return entries 67 } 68 69 // Entry returns the entry by id. 70 func (h *History) Entry(id int64) *Entry { 71 h.Lock() 72 defer h.Unlock() 73 for _, src := range h.items { 74 if src.Stage.ID == id { 75 dst := new(Entry) 76 *dst = *src 77 return dst 78 } 79 } 80 return nil 81 } 82 83 // Limit returns the history limit. 84 func (h *History) Limit() int { 85 if h.limit == 0 { 86 return defaultLimit 87 } 88 return h.limit 89 } 90 91 func (h *History) update(state *pipeline.State) { 92 for _, v := range h.items { 93 if v.Stage.ID == state.Stage.ID { 94 v.Stage = internal.CloneStage(state.Stage) 95 v.Build = internal.CloneBuild(state.Build) 96 v.Repo = internal.CloneRepo(state.Repo) 97 v.Updated = time.Now().UTC() 98 return 99 } 100 } 101 h.items = append(h.items, &Entry{ 102 Stage: internal.CloneStage(state.Stage), 103 Build: internal.CloneBuild(state.Build), 104 Repo: internal.CloneRepo(state.Repo), 105 Created: time.Now(), 106 Updated: time.Now(), 107 }) 108 } 109 110 func (h *History) prune() { 111 if len(h.items) > h.Limit() { 112 h.items = h.items[:h.Limit()-1] 113 } 114 }