Create and propagate contexts wherever possible

This commit is contained in:
Elara 2022-05-11 13:24:12 -07:00
parent c05147518d
commit 60f1eedc9a
9 changed files with 92 additions and 80 deletions

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"sync" "sync"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
@ -8,15 +9,15 @@ import (
"go.arsenm.dev/infinitime" "go.arsenm.dev/infinitime"
) )
func initCallNotifs(dev *infinitime.Device) error { func initCallNotifs(ctx context.Context, dev *infinitime.Device) error {
// Connect to system bus. This connection is for method calls. // Connect to system bus. This connection is for method calls.
conn, err := newSystemBusConn() conn, err := newSystemBusConn(ctx)
if err != nil { if err != nil {
return err return err
} }
// Check if modem manager interface exists // Check if modem manager interface exists
exists, err := modemManagerExists(conn) exists, err := modemManagerExists(ctx, conn)
if err != nil { if err != nil {
return err return err
} }
@ -28,7 +29,7 @@ func initCallNotifs(dev *infinitime.Device) error {
} }
// Connect to system bus. This connection is for monitoring. // Connect to system bus. This connection is for monitoring.
monitorConn, err := newSystemBusConn() monitorConn, err := newSystemBusConn(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -78,13 +79,13 @@ func initCallNotifs(dev *infinitime.Device) error {
switch res { switch res {
case infinitime.CallStatusAccepted: case infinitime.CallStatusAccepted:
// Attempt to accept call // Attempt to accept call
err = acceptCall(conn, callObj) err = acceptCall(ctx, conn, callObj)
if err != nil { if err != nil {
log.Warn().Err(err).Msg("Error accepting call") log.Warn().Err(err).Msg("Error accepting call")
} }
case infinitime.CallStatusDeclined: case infinitime.CallStatusDeclined:
// Attempt to decline call // Attempt to decline call
err = declineCall(conn, callObj) err = declineCall(ctx, conn, callObj)
if err != nil { if err != nil {
log.Warn().Err(err).Msg("Error declining call") log.Warn().Err(err).Msg("Error declining call")
} }
@ -101,9 +102,11 @@ func initCallNotifs(dev *infinitime.Device) error {
return nil return nil
} }
func modemManagerExists(conn *dbus.Conn) (bool, error) { func modemManagerExists(ctx context.Context, conn *dbus.Conn) (bool, error) {
var names []string var names []string
err := conn.BusObject().Call("org.freedesktop.DBus.ListNames", 0).Store(&names) err := conn.BusObject().CallWithContext(
ctx, "org.freedesktop.DBus.ListNames", 0,
).Store(&names)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -122,9 +125,11 @@ func getPhoneNum(conn *dbus.Conn, callObj dbus.BusObject) (string, error) {
} }
// getPhoneNum accepts a call using a DBus connection // getPhoneNum accepts a call using a DBus connection
func acceptCall(conn *dbus.Conn, callObj dbus.BusObject) error { func acceptCall(ctx context.Context, conn *dbus.Conn, callObj dbus.BusObject) error {
// Call Accept() method on DBus object // Call Accept() method on DBus object
call := callObj.Call("org.freedesktop.ModemManager1.Call.Accept", 0) call := callObj.CallWithContext(
ctx, "org.freedesktop.ModemManager1.Call.Accept", 0,
)
if call.Err != nil { if call.Err != nil {
return call.Err return call.Err
} }
@ -132,9 +137,11 @@ func acceptCall(conn *dbus.Conn, callObj dbus.BusObject) error {
} }
// getPhoneNum declines a call using a DBus connection // getPhoneNum declines a call using a DBus connection
func declineCall(conn *dbus.Conn, callObj dbus.BusObject) error { func declineCall(ctx context.Context, conn *dbus.Conn, callObj dbus.BusObject) error {
// Call Hangup() method on DBus object // Call Hangup() method on DBus object
call := callObj.Call("org.freedesktop.ModemManager1.Call.Hangup", 0) call := callObj.CallWithContext(
ctx, "org.freedesktop.ModemManager1.Call.Hangup", 0,
)
if call.Err != nil { if call.Err != nil {
return call.Err return call.Err
} }

14
dbus.go
View File

@ -1,10 +1,14 @@
package main package main
import "github.com/godbus/dbus/v5" import (
"context"
func newSystemBusConn() (*dbus.Conn, error) { "github.com/godbus/dbus/v5"
)
func newSystemBusConn(ctx context.Context) (*dbus.Conn, error) {
// Connect to dbus session bus // Connect to dbus session bus
conn, err := dbus.SystemBusPrivate() conn, err := dbus.SystemBusPrivate(dbus.WithContext(ctx))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -19,9 +23,9 @@ func newSystemBusConn() (*dbus.Conn, error) {
return conn, nil return conn, nil
} }
func newSessionBusConn() (*dbus.Conn, error) { func newSessionBusConn(ctx context.Context) (*dbus.Conn, error) {
// Connect to dbus session bus // Connect to dbus session bus
conn, err := dbus.SessionBusPrivate() conn, err := dbus.SessionBusPrivate(dbus.WithContext(ctx))
if err != nil { if err != nil {
return nil, err return nil, err
} }

2
go.mod
View File

@ -15,7 +15,7 @@ require (
github.com/mozillazg/go-pinyin v0.19.0 github.com/mozillazg/go-pinyin v0.19.0
github.com/rs/zerolog v1.26.1 github.com/rs/zerolog v1.26.1
github.com/urfave/cli/v2 v2.3.0 github.com/urfave/cli/v2 v2.3.0
go.arsenm.dev/infinitime v0.0.0-20220505193916-1533865e4c42 go.arsenm.dev/infinitime v0.0.0-20220511202257-9ed74726c478
go.arsenm.dev/lrpc v0.0.0-20220510090735-af77b121f888 go.arsenm.dev/lrpc v0.0.0-20220510090735-af77b121f888
golang.org/x/text v0.3.7 golang.org/x/text v0.3.7
modernc.org/sqlite v1.17.2 modernc.org/sqlite v1.17.2

4
go.sum
View File

@ -396,8 +396,8 @@ github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.4 h1:zNWRjYUW32G9KirMXYHQHVNFkXvMI7LpgNW2AgYAoIs= github.com/yuin/goldmark v1.4.4 h1:zNWRjYUW32G9KirMXYHQHVNFkXvMI7LpgNW2AgYAoIs=
github.com/yuin/goldmark v1.4.4/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg= github.com/yuin/goldmark v1.4.4/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg=
go.arsenm.dev/infinitime v0.0.0-20220505193916-1533865e4c42 h1:t3gXRa6TEPZ7mOGxkccYke7afkVe5qL+DGHFPkHF+WI= go.arsenm.dev/infinitime v0.0.0-20220511202257-9ed74726c478 h1:HO+fteXuSnnT7po1PhGJK6nk8qMAGN2RqDaVP4sRN8g=
go.arsenm.dev/infinitime v0.0.0-20220505193916-1533865e4c42/go.mod h1:1cBQ3fp6QlRbSqu9kEBAHsVThINj31FtqHIYVsQ7wgg= go.arsenm.dev/infinitime v0.0.0-20220511202257-9ed74726c478/go.mod h1:1cBQ3fp6QlRbSqu9kEBAHsVThINj31FtqHIYVsQ7wgg=
go.arsenm.dev/lrpc v0.0.0-20220510090735-af77b121f888 h1:WrcoTvWsmg5YHq/nWRBMdcRlNfFPfVtfi6eBEVyod8w= go.arsenm.dev/lrpc v0.0.0-20220510090735-af77b121f888 h1:WrcoTvWsmg5YHq/nWRBMdcRlNfFPfVtfi6eBEVyod8w=
go.arsenm.dev/lrpc v0.0.0-20220510090735-af77b121f888/go.mod h1:goK9z735lfXmqlDxu9qN7FS8t0HJHN3PjyDtCToUY4w= go.arsenm.dev/lrpc v0.0.0-20220510090735-af77b121f888/go.mod h1:goK9z735lfXmqlDxu9qN7FS8t0HJHN3PjyDtCToUY4w=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=

29
main.go
View File

@ -19,11 +19,14 @@
package main package main
import ( import (
"context"
_ "embed" _ "embed"
"flag" "flag"
"fmt" "fmt"
"os" "os"
"os/signal"
"strconv" "strconv"
"syscall"
"time" "time"
"github.com/gen2brain/dlgs" "github.com/gen2brain/dlgs"
@ -74,8 +77,24 @@ func main() {
LogLevel: level, LogLevel: level,
} }
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sigCh := make(chan os.Signal, 1)
go func() {
<-sigCh
cancel()
time.Sleep(200 * time.Millisecond)
os.Exit(0)
}()
signal.Notify(
sigCh,
syscall.SIGINT,
syscall.SIGTERM,
)
// Connect to InfiniTime with default options // Connect to InfiniTime with default options
dev, err := infinitime.Connect(opts) dev, err := infinitime.Connect(ctx, opts)
if err != nil { if err != nil {
log.Fatal().Err(err).Msg("Error connecting to InfiniTime") log.Fatal().Err(err).Msg("Error connecting to InfiniTime")
} }
@ -136,25 +155,25 @@ func main() {
} }
// Start control socket // Start control socket
err = initCallNotifs(dev) err = initCallNotifs(ctx, dev)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Error initializing call notifications") log.Error().Err(err).Msg("Error initializing call notifications")
} }
// Initialize notification relay // Initialize notification relay
err = initNotifRelay(dev) err = initNotifRelay(ctx, dev)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Error initializing notification relay") log.Error().Err(err).Msg("Error initializing notification relay")
} }
// Initializa weather // Initializa weather
err = initWeather(dev) err = initWeather(ctx, dev)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Error initializing weather") log.Error().Err(err).Msg("Error initializing weather")
} }
// Initialize metrics collection // Initialize metrics collection
err = initMetrics(dev) err = initMetrics(ctx, dev)
if err != nil { if err != nil {
log.Error().Err(err).Msg("Error intializing metrics collection") log.Error().Err(err).Msg("Error intializing metrics collection")
} }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"database/sql" "database/sql"
"path/filepath" "path/filepath"
"time" "time"
@ -10,7 +11,7 @@ import (
_ "modernc.org/sqlite" _ "modernc.org/sqlite"
) )
func initMetrics(dev *infinitime.Device) error { func initMetrics(ctx context.Context, dev *infinitime.Device) error {
// If metrics disabled, return nil // If metrics disabled, return nil
if !k.Bool("metrics.enabled") { if !k.Bool("metrics.enabled") {
return nil return nil
@ -49,7 +50,7 @@ func initMetrics(dev *infinitime.Device) error {
// If heart rate metrics enabled in config // If heart rate metrics enabled in config
if k.Bool("metrics.heartRate.enabled") { if k.Bool("metrics.heartRate.enabled") {
// Watch heart rate // Watch heart rate
heartRateCh, _, err := dev.WatchHeartRate() heartRateCh, err := dev.WatchHeartRate(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -67,7 +68,7 @@ func initMetrics(dev *infinitime.Device) error {
// If step count metrics enabled in config // If step count metrics enabled in config
if k.Bool("metrics.stepCount.enabled") { if k.Bool("metrics.stepCount.enabled") {
// Watch step count // Watch step count
stepCountCh, _, err := dev.WatchStepCount() stepCountCh, err := dev.WatchStepCount(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -85,7 +86,7 @@ func initMetrics(dev *infinitime.Device) error {
// If battery level metrics enabled in config // If battery level metrics enabled in config
if k.Bool("metrics.battLevel.enabled") { if k.Bool("metrics.battLevel.enabled") {
// Watch battery level // Watch battery level
battLevelCh, _, err := dev.WatchBatteryLevel() battLevelCh, err := dev.WatchBatteryLevel(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -103,7 +104,7 @@ func initMetrics(dev *infinitime.Device) error {
// If motion metrics enabled in config // If motion metrics enabled in config
if k.Bool("metrics.motion.enabled") { if k.Bool("metrics.motion.enabled") {
// Watch motion values // Watch motion values
motionCh, _, err := dev.WatchMotion() motionCh, err := dev.WatchMotion(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -19,6 +19,7 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
@ -27,9 +28,9 @@ import (
"go.arsenm.dev/itd/translit" "go.arsenm.dev/itd/translit"
) )
func initNotifRelay(dev *infinitime.Device) error { func initNotifRelay(ctx context.Context, dev *infinitime.Device) error {
// Connect to dbus session bus // Connect to dbus session bus
bus, err := newSessionBusConn() bus, err := newSessionBusConn(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -40,7 +41,9 @@ func initNotifRelay(dev *infinitime.Device) error {
} }
var flag uint = 0 var flag uint = 0
// Becode monitor for notifications // Becode monitor for notifications
call := bus.BusObject().Call("org.freedesktop.DBus.Monitoring.BecomeMonitor", 0, rules, flag) call := bus.BusObject().CallWithContext(
ctx, "org.freedesktop.DBus.Monitoring.BecomeMonitor", 0, rules, flag,
)
if call.Err != nil { if call.Err != nil {
return call.Err return call.Err
} }

View File

@ -105,22 +105,15 @@ func (i *ITD) WatchHeartRate(ctx *server.Context) error {
return err return err
} }
heartRateCh, cancel, err := i.dev.WatchHeartRate() heartRateCh, err := i.dev.WatchHeartRate(ctx)
if err != nil { if err != nil {
return err return err
} }
go func() { go func() {
// For every heart rate value // For every heart rate value
for { for heartRate := range heartRateCh {
select { ch <- heartRate
case <-ctx.Done():
// Stop notifications if done signal received
cancel()
return
case heartRate := <-heartRateCh:
ch <- heartRate
}
} }
}() }()
@ -137,22 +130,15 @@ func (i *ITD) WatchBatteryLevel(ctx *server.Context) error {
return err return err
} }
battLevelCh, cancel, err := i.dev.WatchBatteryLevel() battLevelCh, err := i.dev.WatchBatteryLevel(ctx)
if err != nil { if err != nil {
return err return err
} }
go func() { go func() {
// For every heart rate value // For every heart rate value
for { for battLevel := range battLevelCh {
select { ch <- battLevel
case <-ctx.Done():
// Stop notifications if done signal received
cancel()
return
case battLevel := <-battLevelCh:
ch <- battLevel
}
} }
}() }()
@ -169,22 +155,15 @@ func (i *ITD) WatchMotion(ctx *server.Context) error {
return err return err
} }
motionValsCh, cancel, err := i.dev.WatchMotion() motionValsCh, err := i.dev.WatchMotion(ctx)
if err != nil { if err != nil {
return err return err
} }
go func() { go func() {
// For every heart rate value // For every heart rate value
for { for motionVals := range motionValsCh {
select { ch <- motionVals
case <-ctx.Done():
// Stop notifications if done signal received
cancel()
return
case motionVals := <-motionValsCh:
ch <- motionVals
}
} }
}() }()
@ -201,22 +180,15 @@ func (i *ITD) WatchStepCount(ctx *server.Context) error {
return err return err
} }
stepCountCh, cancel, err := i.dev.WatchStepCount() stepCountCh, err := i.dev.WatchStepCount(ctx)
if err != nil { if err != nil {
return err return err
} }
go func() { go func() {
// For every heart rate value // For every heart rate value
for { for stepCount := range stepCountCh {
select { ch <- stepCount
case <-ctx.Done():
// Stop notifications if done signal received
cancel()
return
case stepCount := <-stepCountCh:
ch <- stepCount
}
} }
}() }()

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"math" "math"
@ -60,13 +61,13 @@ type OSMData []struct {
var sendWeatherCh = make(chan struct{}, 1) var sendWeatherCh = make(chan struct{}, 1)
func initWeather(dev *infinitime.Device) error { func initWeather(ctx context.Context, dev *infinitime.Device) error {
if !k.Bool("weather.enabled") { if !k.Bool("weather.enabled") {
return nil return nil
} }
// Get location based on string in config // Get location based on string in config
lat, lon, err := getLocation(k.String("weather.location")) lat, lon, err := getLocation(ctx, k.String("weather.location"))
if err != nil { if err != nil {
return err return err
} }
@ -76,7 +77,7 @@ func initWeather(dev *infinitime.Device) error {
go func() { go func() {
for { for {
// Attempt to get weather // Attempt to get weather
data, err := getWeather(lat, lon) data, err := getWeather(ctx, lat, lon)
if err != nil { if err != nil {
log.Warn().Err(err).Msg("Error getting weather data") log.Warn().Err(err).Msg("Error getting weather data")
// Wait 15 minutes before retrying // Wait 15 minutes before retrying
@ -181,10 +182,14 @@ func initWeather(dev *infinitime.Device) error {
// getLocation returns the latitude and longitude // getLocation returns the latitude and longitude
// given a location // given a location
func getLocation(loc string) (lat, lon float64, err error) { func getLocation(ctx context.Context, loc string) (lat, lon float64, err error) {
// Create request URL and perform GET request // Create request URL and perform GET request
reqURL := fmt.Sprintf("https://nominatim.openstreetmap.org/search.php?q=%s&format=jsonv2", url.QueryEscape(loc)) reqURL := fmt.Sprintf("https://nominatim.openstreetmap.org/search.php?q=%s&format=jsonv2", url.QueryEscape(loc))
res, err := http.Get(reqURL) req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
if err != nil {
return
}
res, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
return return
} }
@ -218,9 +223,10 @@ func getLocation(loc string) (lat, lon float64, err error) {
} }
// getWeather gets weather data given a latitude and longitude // getWeather gets weather data given a latitude and longitude
func getWeather(lat, lon float64) (*METResponse, error) { func getWeather(ctx context.Context, lat, lon float64) (*METResponse, error) {
// Create new GET request // Create new GET request
req, err := http.NewRequest( req, err := http.NewRequestWithContext(
ctx,
http.MethodGet, http.MethodGet,
fmt.Sprintf( fmt.Sprintf(
"https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=%.2f&lon=%.2f", "https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=%.2f&lon=%.2f",