1
0
Fork 0
mirror of https://github.com/Luzifer/mapshare.git synced 2024-12-20 14:41:19 +00:00

Add disk retention of state

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2020-01-07 00:49:40 +01:00
parent 2fa10b94cf
commit c11d1e728c
Signed by: luzifer
GPG key ID: DC2729FDD34BE99E
6 changed files with 86 additions and 6 deletions

View file

@ -8,6 +8,6 @@
This project is a very simple and data protecting alternative to sharing a location through Glympse or similar services.
You can setup your own instance in minutes, it does not require any database (even retained location data is dropped on restart of the service!) and you can share your location from a mobile browser. To view the location nothing more than a browser is required.
You can setup your own instance in minutes, it does not require any database (though you can have the retained locations stored on disk) and you can share your location from a mobile browser. To view the location nothing more than a browser is required.
When sharing a location you have the choice to select whether the server should retain the location data (until restart) or just pipe it through. Retaining the data has the advantage new viewers (or viewers whose websocket has reconnected) instantly see your location. When not retaining data the data is received, sent to all connected sockets and afterwards instantly forgotten.
When sharing a location you have the choice to select whether the server should retain the location data or just pipe it through. Retaining the data has the advantage new viewers (or viewers whose websocket has reconnected) instantly see your location. When not retaining data the data is received, sent to all connected sockets and afterwards instantly forgotten.

1
go.mod
View file

@ -8,6 +8,7 @@ require (
github.com/gorilla/mux v1.7.3
github.com/gorilla/websocket v1.4.1
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.4.2
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e // indirect
)

2
go.sum
View file

@ -12,6 +12,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=

View file

@ -58,7 +58,7 @@ func handleMapSocket(w http.ResponseWriter, r *http.Request) {
// In case a retained position is available queue it
reqRetainerLock.RLock()
if p, ok := reqRetainer[mapID]; ok {
if p, ok := reqRetainer[mapID]; ok && time.Since(p.Time) < cfg.StateTimeout {
updates <- p
}
reqRetainerLock.RUnlock()
@ -111,6 +111,12 @@ func handleMapSubmit(w http.ResponseWriter, r *http.Request) {
}
reqRetainerLock.Unlock()
go func() {
if err := retainState(); err != nil {
log.WithError(err).Error("Unable to retain state to disk")
}
}()
reqDistributorsLock.RLock()
defer reqDistributorsLock.RUnlock()

View file

@ -4,6 +4,7 @@ import (
"fmt"
"net/http"
"os"
"time"
"github.com/gorilla/mux"
log "github.com/sirupsen/logrus"
@ -15,6 +16,8 @@ var (
cfg = struct {
Listen string `flag:"listen" default:":3000" description:"Port/IP to listen on"`
LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error, fatal)"`
StateFile string `flag:"state-file" default:"" description:"Where to store retained locations (empty for no state)"`
StateTimeout time.Duration `flag:"state-timeout" default:"24h" description:"When to drop retained states"`
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
}{}
@ -22,6 +25,7 @@ var (
)
func init() {
rconfig.AutoEnv(true)
if err := rconfig.ParseAndValidate(&cfg); err != nil {
log.Fatalf("Unable to parse commandline options: %s", err)
}
@ -39,6 +43,10 @@ func init() {
}
func main() {
if err := loadState(); err != nil {
log.WithError(err).Fatal("Unable to load state")
}
r := mux.NewRouter()
r.HandleFunc("/", handleRedirectRandom).Methods(http.MethodGet)

63
state.go Normal file
View file

@ -0,0 +1,63 @@
package main
import (
"encoding/json"
"os"
"time"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
func loadState() error {
if cfg.StateFile == "" {
// No state file, no retaining
return nil
}
if _, err := os.Stat(cfg.StateFile); err != nil {
log.WithError(err).Warn("Unable to load state, using empty state")
if os.IsNotExist(err) {
return nil
}
return errors.Wrap(err, "Unable to access state file")
}
reqRetainerLock.Lock()
defer reqRetainerLock.Unlock()
f, err := os.Open(cfg.StateFile)
if err != nil {
return errors.Wrap(err, "Unable to open state file")
}
defer f.Close()
return errors.Wrap(json.NewDecoder(f).Decode(&reqRetainer), "Unable to decode state file")
}
func retainState() error {
if cfg.StateFile == "" {
// No state file, no retaining
return nil
}
f, err := os.Create(cfg.StateFile)
if err != nil {
return errors.Wrap(err, "Unable to create state file")
}
defer f.Close()
reqRetainerLock.RLock()
defer reqRetainerLock.RUnlock()
var tmpState = make(map[string]position)
for m, p := range reqRetainer {
if time.Since(p.Time) > cfg.StateTimeout {
continue
}
tmpState[m] = p
}
return errors.Wrap(json.NewEncoder(f).Encode(tmpState), "Unable to encode state file")
}