github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/agent/mcorpc/client/util.go (about) 1 // Copyright (c) 2020-2021, R.I. Pienaar and the Choria Project contributors 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package client 6 7 import ( 8 "context" 9 "encoding/json" 10 "errors" 11 "fmt" 12 "math" 13 "time" 14 15 "github.com/choria-io/go-choria/protocol" 16 ) 17 18 // ParseReply parses a protocol reply into a RPC Reply 19 func ParseReply(reply protocol.Reply) (*RPCReply, error) { 20 r, err := ParseReplyData([]byte(reply.Message())) 21 if err != nil { 22 return nil, err 23 } 24 25 r.Time = reply.Time().UTC() 26 r.Sender = reply.SenderID() 27 28 return r, nil 29 } 30 31 // ParseReplyData parses reply data and populates a Reply and custom Data 32 func ParseReplyData(source []byte) (*RPCReply, error) { 33 reply := &RPCReply{} 34 35 err := json.Unmarshal(source, reply) 36 if err != nil { 37 return reply, fmt.Errorf("could not decode source data: %s", err) 38 } 39 40 return reply, nil 41 } 42 43 // InGroups calls f for sub slices of a slice where every slice 44 // is at most `size` big 45 func InGroups(set []string, size int, f func([]string) error) error { 46 count := math.Ceil(float64(len(set)) / float64(size)) 47 48 for i := 0; i < int(count); i++ { 49 start := i * int(size) 50 end := start + int(size) 51 52 if end > len(set) { 53 end = len(set) 54 } 55 56 err := f(set[start:end]) 57 if err != nil { 58 return err 59 } 60 } 61 62 return nil 63 } 64 65 // InterruptableSleep sleep for the duration of the n'th wait cycle 66 // in a way that can be interrupted by the context. An error is returned 67 // if the context cancels the sleep 68 func InterruptableSleep(ctx context.Context, d time.Duration) error { 69 timer := time.NewTimer(d) 70 71 select { 72 case <-timer.C: 73 return nil 74 case <-ctx.Done(): 75 return errors.New("sleep interrupted by context") 76 } 77 }