package main import ( "context" "time" "tera-clone/services/tera-api/internal/domain" ) type resetButtonStateReader interface { ResetButtonPressed(context.Context) (bool, error) } type factoryResetStore interface { FactoryReset(context.Context) (domain.Operation, error) } func runFactoryResetButtonMonitor( ctx context.Context, reader resetButtonStateReader, store factoryResetStore, pollInterval time.Duration, holdDuration time.Duration, onReset func(domain.Operation), onError func(error), ) { if pollInterval <= 0 { pollInterval = 100 * time.Millisecond } if holdDuration <= 0 { holdDuration = time.Second } ticker := time.NewTicker(pollInterval) defer ticker.Stop() var pressedAt time.Time handled := false unavailable := false for { select { case <-ctx.Done(): return case <-ticker.C: probeContext, cancel := context.WithTimeout(ctx, pollInterval) pressed, err := reader.ResetButtonPressed(probeContext) cancel() if err != nil { if !unavailable && onError != nil { onError(err) } unavailable = true pressedAt = time.Time{} handled = false continue } unavailable = false if !pressed { pressedAt = time.Time{} handled = false continue } if pressedAt.IsZero() { pressedAt = time.Now() continue } if handled || time.Since(pressedAt) < holdDuration { continue } resetContext, resetCancel := context.WithTimeout(ctx, 15*time.Second) operation, resetErr := store.FactoryReset(resetContext) resetCancel() handled = true if resetErr != nil { if onError != nil { onError(resetErr) } continue } if onReset != nil { onReset(operation) } } } }