From 406b19fd05387c5f488ebaef67151939c11a4721 Mon Sep 17 00:00:00 2001 From: Madh93 Date: Sun, 23 Jul 2023 23:39:56 +0100 Subject: [PATCH] fetch: fetch API data concurrently --- internal/toffu/signs.go | 16 -------- internal/toffu/toffu.go | 81 ++++++++++++++++++-------------------- internal/toffu/utils.go | 30 ++++++++++++++ internal/woffuapi/signs.go | 7 ++++ 4 files changed, 76 insertions(+), 58 deletions(-) delete mode 100644 internal/toffu/signs.go diff --git a/internal/toffu/signs.go b/internal/toffu/signs.go deleted file mode 100644 index 388a8af..0000000 --- a/internal/toffu/signs.go +++ /dev/null @@ -1,16 +0,0 @@ -package toffu - -import ( - "github.com/Madh93/toffu/internal/woffuapi" -) - -type Signs struct { - signs woffuapi.Signs -} - -func (s Signs) hasAlreadyClockedIn() bool { - if len(s.signs) > 0 { - return s.signs[len(s.signs)-1].SignIn - } - return false -} diff --git a/internal/toffu/toffu.go b/internal/toffu/toffu.go index 49d9c99..64f4124 100644 --- a/internal/toffu/toffu.go +++ b/internal/toffu/toffu.go @@ -10,8 +10,11 @@ import ( ) type Toffu struct { - api *woffuapi.WoffuAPI - signs *Signs + api *woffuapi.WoffuAPI + signs woffuapi.Signs + signSlots woffuapi.SignSlots + workday *woffuapi.WorkDay + userId int } func New() *Toffu { @@ -26,8 +29,29 @@ func (t *Toffu) SetAPI(api *woffuapi.WoffuAPI) { t.api = api } -func (t *Toffu) SetSigns(signs woffuapi.Signs) { - t.signs = &Signs{signs: signs} +func (t *Toffu) setSigns() (err error) { + t.signs, err = t.api.GetSigns() + return +} + +func (t *Toffu) setSignSlots() (err error) { + t.signSlots, err = t.api.GetSignSlots() + return +} + +func (t *Toffu) setWorkday() (err error) { + err = t.setUserId() + if err != nil { + return + } + + t.workday, err = t.api.GetUserWorkDay(t.userId) + return +} + +func (t *Toffu) setUserId() (err error) { + t.userId, err = getUserId() + return } func (t *Toffu) GenerateToken() (err error) { @@ -70,31 +94,20 @@ func (t *Toffu) ClockIn() (err error) { return err } - userId, err := getUserId() - if err != nil { - return - } - - signs, err := t.api.GetSigns() + err = runConcurrently(t.setSigns, t.setWorkday) if err != nil { return err } - t.SetSigns(signs) - if t.signs.hasAlreadyClockedIn() { + if t.signs.HasAlreadyClockedIn() { return errors.New("error clocking in, you have already clocked in") } - workday, err := t.api.GetUserWorkDay(userId) - if err != nil { - return err - } - - if workday.ScheduleHours <= 0.0 { + if t.workday.ScheduleHours <= 0.0 { return errors.New("error clocking in, no scheduled working hours today") } - err = t.api.Sign(userId) + err = t.api.Sign(t.userId) if err != nil { return fmt.Errorf("error clocking in: %v", err) } @@ -112,22 +125,16 @@ func (t *Toffu) ClockOut() (err error) { return err } - userId, err := getUserId() - if err != nil { - return - } - - signs, err := t.api.GetSigns() + err = runConcurrently(t.setSigns, t.setUserId) if err != nil { return err } - t.SetSigns(signs) - if !t.signs.hasAlreadyClockedIn() { + if !t.signs.HasAlreadyClockedIn() { return errors.New("error clocking out, you have not clocked in or you have already clocked out") } - err = t.api.Sign(userId) + err = t.api.Sign(t.userId) if err != nil { return fmt.Errorf("error clocking out: %v", err) } @@ -143,7 +150,7 @@ func (t *Toffu) GetStatus() (err error) { return err } - slots, err := t.api.GetSignSlots() + err = runConcurrently(t.setSignSlots, t.setWorkday) if err != nil { return err } @@ -151,7 +158,7 @@ func (t *Toffu) GetStatus() (err error) { // Current status status := "" - if len(slots) > 0 && (woffuapi.SignSlotEvent{}) == slots[len(slots)-1].Out { + if len(t.signSlots) > 0 && (woffuapi.SignSlotEvent{}) == t.signSlots[len(t.signSlots)-1].Out { status = "In Office" } else { status = "Out of Office" @@ -166,7 +173,7 @@ func (t *Toffu) GetStatus() (err error) { return err } - for _, slot := range slots { + for _, slot := range t.signSlots { inTime, _ := time.Parse("15:04:05", slot.In.ShortTrueTime) outTime, _ := time.Parse("15:04:05", time.Now().In(location).Format("15:04:05")) // In Office @@ -182,17 +189,7 @@ func (t *Toffu) GetStatus() (err error) { } // Remaining hours - userId, err := getUserId() - if err != nil { - return - } - - workday, err := t.api.GetUserWorkDay(userId) - if err != nil { - return err - } - - remainingDuration := time.Duration(workday.ScheduleHours*float64(time.Hour)) - totalDuration + remainingDuration := time.Duration(t.workday.ScheduleHours*float64(time.Hour)) - totalDuration // Show hours worked and remaining hours fmt.Printf("Total hours worked today: %s", secondsToHumanReadable(totalDuration)) diff --git a/internal/toffu/utils.go b/internal/toffu/utils.go index 36199f2..7a2b274 100644 --- a/internal/toffu/utils.go +++ b/internal/toffu/utils.go @@ -8,6 +8,7 @@ import ( "runtime" "strconv" "strings" + "sync" "time" "github.com/spf13/viper" @@ -122,3 +123,32 @@ func secondsToHumanReadable(duration time.Duration) string { return fmt.Sprintf("%dh %dm %ds", hours, minutes, seconds) } + +func runConcurrently(funcs ...func() error) (err error) { + var wg sync.WaitGroup + wg.Add(len(funcs)) + errChan := make(chan error, len(funcs)) + + // Run goroutines + for _, f := range funcs { + go func(fn func() error) { + defer wg.Done() + if err := fn(); err != nil { + errChan <- err + } + }(f) + } + + // Wait for all goroutines to finish + wg.Wait() + close(errChan) + + // Collect any errors + for err := range errChan { + if err != nil { + return err + } + } + + return nil +} diff --git a/internal/woffuapi/signs.go b/internal/woffuapi/signs.go index d04aec8..a4f0563 100644 --- a/internal/woffuapi/signs.go +++ b/internal/woffuapi/signs.go @@ -14,6 +14,13 @@ type Signs []struct { TrueDate string `json:"TrueDate"` // Local Time } +func (s Signs) HasAlreadyClockedIn() bool { + if len(s) > 0 { + return s[len(s)-1].SignIn + } + return false +} + func (w WoffuAPI) GetSigns() (Signs, error) { if w.auth.Type() != "TokenAuth" { return nil, errors.New("token authentication is required")