Skip to content

Commit

Permalink
feat: SystemD socket
Browse files Browse the repository at this point in the history
Created a systemd socket unit will be responsible to listen the
connection, and when something connects to it, the daemon will
initialize the service.

Hooks were also updated to have a smooth transition between versions
installations to avoid any downtime.

Additionally, Golang code was updated to read the socket created, and
deal with service shutdown.
  • Loading branch information
faabiosr committed Oct 22, 2023
1 parent e0b5ac8 commit 6a9de30
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .goreleaser.yaml
Expand Up @@ -49,6 +49,8 @@ nfpms:
contents:
- src: "env/debian/movies.service"
dst: "/lib/systemd/system/movies.service"
- src: "env/debian/movies.socket"
dst: "/lib/systemd/system/movies.socket"
- src: "env/debian/movies.conf"
dst: "/etc/default/movies"
type: config
Expand Down
36 changes: 35 additions & 1 deletion cmd/movies/main.go
@@ -1,9 +1,13 @@
package main

import (
"context"
"os"
"os/signal"
"path/filepath"
"time"

"github.com/coreos/go-systemd/v22/activation"
"github.com/labstack/echo/v4"
mw "github.com/labstack/echo/v4/middleware"
glog "github.com/labstack/gommon/log"
Expand All @@ -19,6 +23,8 @@ const (
dbPathEnv = "MOVIES_DB_PATH"
)

const timeout = 10 * time.Second

func main() {
e := echo.New()
e.HidePort = true
Expand Down Expand Up @@ -52,7 +58,35 @@ func main() {
// Start server
e.Logger.Infof("%s service", appName)

if err := e.Start(appAddr); err != nil {
go func() {
if err := start(e, appAddr); err != nil {
e.Logger.Info("shutting down the service")
}
}()

// Graceful shutdown
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)

<-quit

ctx, cancel := context.WithTimeout(context.TODO(), timeout)
defer cancel()

if err := e.Shutdown(ctx); err != nil {
e.Logger.Fatal(err)
}
}

func start(e *echo.Echo, host string) error {
listeners, err := activation.Listeners()
if err != nil {
return nil
}

if len(listeners) > 0 {
e.Listener = listeners[0]
}

return e.Start(host)
}
2 changes: 2 additions & 0 deletions env/debian/movies.service
@@ -1,6 +1,8 @@
[Unit]
Description=Manages movie collection throught API
Documentation="https://github.com/faabiosr/go-movies-demo"
After=network.target
Requires=movies.socket

[Service]
EnvironmentFile=/etc/default/movies
Expand Down
11 changes: 11 additions & 0 deletions env/debian/movies.socket
@@ -0,0 +1,11 @@
[Unit]
Description=Manages movie collection throught API
Documentation="https://github.com/faabiosr/go-movies-demo"

[Socket]
ListenStream=8000
SocketUser=movies-demo
SocketGroup=movies-demo

[Install]
WantedBy=sockets.target
15 changes: 12 additions & 3 deletions env/debian/post-install.sh
Expand Up @@ -5,6 +5,7 @@ set -e
MOVIES_DB_PATH=/var/lib/movies-demo
MOVIES_USER=movies-demo
MOVIES_SERVICE=movies.service
MOVIES_SOCKET=movies.socket

if [ "$1" = "configure" ]; then
# creating user and group
Expand All @@ -30,16 +31,24 @@ if [ "$1" = "configure" ]; then
deb-systemd-helper update-state $MOVIES_SERVICE >/dev/null || true
fi

# enable systemd socket
deb-systemd-helper unmask $MOVIES_SOCKET >/dev/null || true

if deb-systemd-helper --quiet was-enabled $MOVIES_SOCKET; then
deb-systemd-helper enable $MOVIES_SOCKET >/dev/null || true
else
deb-systemd-helper update-state $MOVIES_SOCKET >/dev/null || true
fi

# starting service
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true

if [ -n "$2" ]; then
_dh_action=restart
deb-systemd-invoke restart $MOVIES_SERVICE >/dev/null || true
else
_dh_action=start
deb-systemd-invoke start $MOVIES_SOCKET >/dev/null || true
fi

deb-systemd-invoke $_dh_action $MOVIES_SERVICE >/dev/null || true
fi
fi
14 changes: 12 additions & 2 deletions env/debian/post-remove.sh
Expand Up @@ -4,6 +4,7 @@ set -e

MOVIES_DB_PATH=/var/lib/movies-demo
MOVIES_SERVICE=movies.service
MOVIES_SOCKET=movies.socket

if [ "$1" = "remove" ]; then
if [ -f "$MOVIES_DB_PATH/catalog.db" ]; then
Expand All @@ -18,11 +19,20 @@ if [ "$1" = "remove" ]; then
systemctl --system daemon-reload >/dev/null || true
fi

deb-systemd-helper mask $MOVIES_SERVICE $MOVIES_SOCKET >/dev/null || true
fi

if [ "$1" = "upgrade" ]; then
# disabling service
if [ -d /run/systemd/system ]; then
systemctl --system daemon-reload >/dev/null || true
fi

deb-systemd-helper mask $MOVIES_SERVICE >/dev/null || true
fi

if [ "$1" = "purge" ]; then
# disabling service
deb-systemd-helper purge $MOVIES_SERVICE >/dev/null || true
deb-systemd-helper unmask $MOVIES_SERVICE >/dev/null || true
deb-systemd-helper purge $MOVIES_SERVICE $MOVIES_SOCKET >/dev/null || true
deb-systemd-helper unmask $MOVIES_SERVICE $MOVIES_SOCKET >/dev/null || true
fi
16 changes: 13 additions & 3 deletions env/debian/pre-remove.sh
Expand Up @@ -3,8 +3,18 @@
set -e

MOVIES_SERVICE=movies.service
MOVIES_SOCKET=movies.socket

# stopping service
if [ -d /run/systemd/system ]; then
deb-systemd-invoke stop $MOVIES_SERVICE >/dev/null || true
if [ "$1" = "remove" ]; then
# stopping service and socket
if [ -d /run/systemd/system ]; then
deb-systemd-invoke stop $MOVIES_SERVICE $MOVIES_SOCKET >/dev/null || true
fi
fi

if [ "$1" = "upgrade" ]; then
# stopping service
if [ -d /run/systemd/system ]; then
deb-systemd-invoke stop $MOVIES_SERVICE >/dev/null || true
fi
fi
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -3,6 +3,7 @@ module github.com/faabiosr/go-movies-demo
go 1.21

require (
github.com/coreos/go-systemd/v22 v22.5.0
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
github.com/gofrs/uuid/v5 v5.0.0
github.com/labstack/echo/v4 v4.11.2
Expand Down
3 changes: 3 additions & 0 deletions go.sum
@@ -1,10 +1,13 @@
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
Expand Down

0 comments on commit 6a9de30

Please sign in to comment.