@@ -4,11 +4,14 @@ import (
44 "context"
55 "encoding/json"
66 "fmt"
7+ "hash/fnv"
78 "net/http"
89 "time"
910
1011 "reverse-watch/config"
1112 "reverse-watch/domain/dto"
13+ "reverse-watch/domain/ingestors"
14+ "reverse-watch/domain/leader"
1215 "reverse-watch/domain/models"
1316 "reverse-watch/domain/repository"
1417 "reverse-watch/errors"
@@ -21,18 +24,22 @@ type csfloatIngestor struct {
2124 log * zap.SugaredLogger
2225 cfg * config.Config
2326 factory repository.Factory
27+ elector leader.Elector
2428
2529 ctx context.Context
2630 cancel context.CancelFunc
2731 stopped chan struct {}
2832}
2933
30- func NewCSFloatIngestor (ctx context.Context , factory repository.Factory , cfg * config.Config , logger * zap.SugaredLogger ) * csfloatIngestor {
34+ var _ ingestors.Ingestor = (* csfloatIngestor )(nil )
35+
36+ func NewCSFloatIngestor (ctx context.Context , factory repository.Factory , elector leader.Elector , cfg * config.Config , log * zap.SugaredLogger ) ingestors.Ingestor {
3137 ingestorCtx , cancel := context .WithCancel (ctx )
3238 return & csfloatIngestor {
33- log : logger ,
39+ log : log ,
3440 cfg : cfg ,
3541 factory : factory ,
42+ elector : elector ,
3643 ctx : ingestorCtx ,
3744 cancel : cancel ,
3845 stopped : make (chan struct {}),
@@ -56,7 +63,7 @@ type errorResponse struct {
5663}
5764
5865// fetch reversal warnings from CSFloat
59- func (i * csfloatIngestor ) fetch (cursor * uint ) ([]* slimWarning , * uint , error ) {
66+ func (i * csfloatIngestor ) fetch (ctx context. Context , cursor * uint ) ([]* slimWarning , * uint , error ) {
6067 // The day before Valve introduced trade reversals
6168 startTime := time .Date (2025 , 7 , 14 , 0 , 0 , 0 , 0 , time .UTC )
6269 endTime := time .Now ().Add (- 5 * time .Minute )
@@ -71,7 +78,7 @@ func (i *csfloatIngestor) fetch(cursor *uint) ([]*slimWarning, *uint, error) {
7178 return nil , nil , err
7279 }
7380 r .Header .Set ("X-Secret-Key" , i .cfg .Ingestors .CSFloat .SecretKey )
74- r = r .WithContext (i . ctx )
81+ r = r .WithContext (ctx )
7582
7683 client := & http.Client {}
7784 resp , err := client .Do (r )
@@ -120,7 +127,7 @@ func (i *csfloatIngestor) process(warnings []*slimWarning) error {
120127 return nil
121128}
122129
123- func (i * csfloatIngestor ) sync () error {
130+ func (i * csfloatIngestor ) sync (ctx context. Context ) error {
124131 // Fetch the most recent reversals created by CSFloat
125132 reversals , err := i .factory .Reversal ().List (& dto.ReversalListOptions {
126133 MarketplaceSlug : util .Ptr ("csfloat" ),
@@ -140,7 +147,13 @@ func (i *csfloatIngestor) sync() error {
140147 }
141148
142149 for {
143- warnings , nextCursor , err := i .fetch (cursor )
150+ select {
151+ case <- ctx .Done ():
152+ return ctx .Err ()
153+ default :
154+ }
155+
156+ warnings , nextCursor , err := i .fetch (ctx , cursor )
144157 if err != nil {
145158 return fmt .Errorf ("failed to fetch warnings with cursor %v: %v" , cursor , err )
146159 }
@@ -161,26 +174,24 @@ func (i *csfloatIngestor) sync() error {
161174}
162175
163176func (i * csfloatIngestor ) Start () {
164- i .log .Info ("Starting CSFloat ingestor" )
177+ i .log .Info ("starting csfloat ingestor" )
165178 go func () {
166179 defer close (i .stopped )
167180
168- for {
169- if err := i .sync (); err != nil {
170- i .log .Errorf ("failed to sync reversals: %v" , err )
171- }
181+ h := fnv .New32a ()
182+ h .Write ([]byte ("csfloat_ingestor_leader" ))
183+ lockKey := h .Sum32 ()
172184
173- select {
174- case <- time .After (30 * time .Minute ):
175- case <- i .ctx .Done ():
176- return
185+ i .elector .Run (i .ctx , lockKey , 30 * time .Minute , func (ctx context.Context ) {
186+ if err := i .sync (ctx ); err != nil {
187+ i .log .Errorf ("failed to sync reversals: %v" , err )
177188 }
178- }
189+ })
179190 }()
180191}
181192
182193func (i * csfloatIngestor ) Stop () {
183- i .log .Infof ("Stopping CSFloat ingestor" )
194+ i .log .Infof ("stopping csfloat ingestor" )
184195 i .cancel ()
185196 <- i .stopped
186197}
0 commit comments