Create and propagate contexts wherever possible

This commit is contained in:
Arsen Musayelyan 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
import (
"context"
"sync"
"github.com/godbus/dbus/v5"
@ -8,15 +9,15 @@ import (
"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.
conn, err := newSystemBusConn()
conn, err := newSystemBusConn(ctx)
if err != nil {
return err
}
// Check if modem manager interface exists
exists, err := modemManagerExists(conn)
exists, err := modemManagerExists(ctx, conn)
if err != nil {
return err
}
@ -28,7 +29,7 @@ func initCallNotifs(dev *infinitime.Device) error {
}
// Connect to system bus. This connection is for monitoring.
monitorConn, err := newSystemBusConn()
monitorConn, err := newSystemBusConn(ctx)
if err != nil {
return err
}
@ -78,13 +79,13 @@ func initCallNotifs(dev *infinitime.Device) error {
switch res {
case infinitime.CallStatusAccepted:
// Attempt to accept call
err = acceptCall(conn, callObj)
err = acceptCall(ctx, conn, callObj)
if err != nil {
log.Warn().Err(err).Msg("Error accepting call")
}
case infinitime.CallStatusDeclined:
// Attempt to decline call
err = declineCall(conn, callObj)
err = declineCall(ctx, conn, callObj)
if err != nil {
log.Warn().Err(err).Msg("Error declining call")
}
@ -101,9 +102,11 @@ func initCallNotifs(dev *infinitime.Device) error {
return nil
}
func modemManagerExists(conn *dbus.Conn) (bool, error) {
func modemManagerExists(ctx context.Context, conn *dbus.Conn) (bool, error) {
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 {
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
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 := callObj.Call("org.freedesktop.ModemManager1.Call.Accept", 0)
call := callObj.CallWithContext(
ctx, "org.freedesktop.ModemManager1.Call.Accept", 0,
)
if call.Err != nil {
return call.Err
}
@ -132,9 +137,11 @@ func acceptCall(conn *dbus.Conn, callObj dbus.BusObject) error {
}
// 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 := callObj.Call("org.freedesktop.ModemManager1.Call.Hangup", 0)
call := callObj.CallWithContext(
ctx, "org.freedesktop.ModemManager1.Call.Hangup", 0,
)
if call.Err != nil {
return call.Err
}

14
dbus.go
View File

@ -1,10 +1,14 @@
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
conn, err := dbus.SystemBusPrivate()
conn, err := dbus.SystemBusPrivate(dbus.WithContext(ctx))
if err != nil {
return nil, err
}
@ -19,9 +23,9 @@ func newSystemBusConn() (*dbus.Conn, error) {
return conn, nil
}
func newSessionBusConn() (*dbus.Conn, error) {
func newSessionBusConn(ctx context.Context) (*dbus.Conn, error) {
// Connect to dbus session bus
conn, err := dbus.SessionBusPrivate()
conn, err := dbus.SessionBusPrivate(dbus.WithContext(ctx))
if err != nil {
return nil, err
}

2
go.mod
View File

@ -15,7 +15,7 @@ require (
github.com/mozillazg/go-pinyin v0.19.0
github.com/rs/zerolog v1.26.1
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
golang.org/x/text v0.3.7
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.4 h1:zNWRjYUW32G9KirMXYHQHVNFkXvMI7LpgNW2AgYAoIs=
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-20220505193916-1533865e4c42/go.mod h1:1cBQ3fp6QlRbSqu9kEBAHsVThINj31FtqHIYVsQ7wgg=
go.arsenm.dev/infinitime v0.0.0-20220511202257-9ed74726c478 h1:HO+fteXuSnnT7po1PhGJK6nk8qMAGN2RqDaVP4sRN8g=
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/go.mod h1:goK9z735lfXmqlDxu9qN7FS8t0HJHN3PjyDtCToUY4w=
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
import (
"context"
_ "embed"
"flag"
"fmt"
"os"
"os/signal"
"strconv"
"syscall"
"time"
"github.com/gen2brain/dlgs"
@ -74,8 +77,24 @@ func main() {
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
dev, err := infinitime.Connect(opts)
dev, err := infinitime.Connect(ctx, opts)
if err != nil {
log.Fatal().Err(err).Msg("Error connecting to InfiniTime")
}
@ -136,25 +155,25 @@ func main() {
}
// Start control socket
err = initCallNotifs(dev)
err = initCallNotifs(ctx, dev)
if err != nil {
log.Error().Err(err).Msg("Error initializing call notifications")
}
// Initialize notification relay
err = initNotifRelay(dev)
err = initNotifRelay(ctx, dev)
if err != nil {
log.Error().Err(err).Msg("Error initializing notification relay")
}
// Initializa weather
err = initWeather(dev)
err = initWeather(ctx, dev)
if err != nil {
log.Error().Err(err).Msg("Error initializing weather")
}
// Initialize metrics collection
err = initMetrics(dev)
err = initMetrics(ctx, dev)
if err != nil {
log.Error().Err(err).Msg("Error intializing metrics collection")
}

View File

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

View File

@ -19,6 +19,7 @@
package main
import (
"context"
"fmt"
"github.com/godbus/dbus/v5"
@ -27,9 +28,9 @@ import (
"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
bus, err := newSessionBusConn()
bus, err := newSessionBusConn(ctx)
if err != nil {
return err
}
@ -40,7 +41,9 @@ func initNotifRelay(dev *infinitime.Device) error {
}
var flag uint = 0
// 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 {
return call.Err
}

View File

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

View File

@ -1,6 +1,7 @@
package main
import (
"context"
"encoding/json"
"fmt"
"math"
@ -60,13 +61,13 @@ type OSMData []struct {
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") {
return nil
}
// 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 {
return err
}
@ -76,7 +77,7 @@ func initWeather(dev *infinitime.Device) error {
go func() {
for {
// Attempt to get weather
data, err := getWeather(lat, lon)
data, err := getWeather(ctx, lat, lon)
if err != nil {
log.Warn().Err(err).Msg("Error getting weather data")
// Wait 15 minutes before retrying
@ -181,10 +182,14 @@ func initWeather(dev *infinitime.Device) error {
// getLocation returns the latitude and longitude
// 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
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 {
return
}
@ -218,9 +223,10 @@ func getLocation(loc string) (lat, lon float64, err error) {
}
// 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
req, err := http.NewRequest(
req, err := http.NewRequestWithContext(
ctx,
http.MethodGet,
fmt.Sprintf(
"https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=%.2f&lon=%.2f",