Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: UI config auto generation #72

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ EXPOSE 8080 9090

# Define entrypoint
ENTRYPOINT [ "readflow" ]

# Define command
CMD [ "serve" ]
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ distribution:

## Start development server (aka: a test database instance)
dev-server:
docker-compose -f docker-compose.dev.yml down
docker-compose -f docker-compose.dev.yml up
docker compose -f docker-compose.dev.yml down
docker compose -f docker-compose.dev.yml up
.PHONY: dev-server

## Deploy containers to Docker host
Expand Down
10 changes: 10 additions & 0 deletions cmd/all/index.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package all

import (
// activate init-config command
_ "github.com/ncarlier/readflow/cmd/init-config"
// activate serve command
_ "github.com/ncarlier/readflow/cmd/serve"
// activate version command
_ "github.com/ncarlier/readflow/cmd/version"
)
32 changes: 32 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"flag"
"fmt"
"os"
)

var (
// ConfigFlag is the flag used to load the config file
ConfigFlag string
)

func init() {
defaultValue := ""
if value, ok := os.LookupEnv("READFLOW_CONFIG"); ok {
defaultValue = value
}
flag.StringVar(&ConfigFlag, "c", defaultValue, "Configuration file to load [ENV: READFLOW_CONFIG]")
flag.Usage = func() {
out := flag.CommandLine.Output()
fmt.Fprintf(out, "readflow is a news-reading (or read-it-later) solution focused on versatility and simplicity.\n")
fmt.Fprintf(out, "\nUsage:\n readflow [flags] [command]\n")
fmt.Fprintf(out, "\nAvailable Commands:\n")
for _, c := range Commands {
c.Usage()
}
fmt.Fprintf(out, "\nFlags:\n")
flag.PrintDefaults()
fmt.Fprintf(out, "\nUse \"reaflow [command] --help\" for more information about a command.\n\n")
}
}
15 changes: 15 additions & 0 deletions cmd/helper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cmd

import "strings"

// GetFirstCommand restun first command of argument list
func GetFirstCommand(args []string) (name string, index int) {
for idx, arg := range args {
if strings.HasPrefix(arg, "-") {
// ignore flags
continue
}
return arg, idx
}
return "", -1
}
39 changes: 39 additions & 0 deletions cmd/init-config/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package initconfig

import (
"flag"
"fmt"

"github.com/ncarlier/readflow/cmd"
"github.com/ncarlier/readflow/pkg/config"
)

const cmdName = "init-config"

type InitConfigCmd struct {
filename string
flagSet *flag.FlagSet
}

func (c *InitConfigCmd) Exec(args []string, conf *config.Config) error {
if err := c.flagSet.Parse(args); err != nil {
return err
}
return conf.WriteDefaultConfigFile(c.filename)
}

func (c *InitConfigCmd) Usage() {
fmt.Fprintf(c.flagSet.Output(), " %s\tInit configuration file\n", cmdName)
}

func newInitConfigCmd() cmd.Cmd {
c := &InitConfigCmd{
flagSet: flag.NewFlagSet(cmdName, flag.ExitOnError),
}
c.flagSet.StringVar(&c.filename, "f", "config.toml", "Configuration file to create")
return c
}

func init() {
cmd.Add(cmdName, newInitConfigCmd)
}
12 changes: 12 additions & 0 deletions cmd/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package cmd

// Creator function for an output
type Creator func() Cmd

// Commands registry
var Commands = map[string]Cmd{}

// Add output to the registry
func Add(name string, creator Creator) {
Commands[name] = creator()
}
35 changes: 35 additions & 0 deletions cmd/serve/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package serve

import (
"flag"
"fmt"

"github.com/ncarlier/readflow/cmd"
"github.com/ncarlier/readflow/pkg/config"
)

const cmdName = "serve"

type ServeCmd struct {
flagSet *flag.FlagSet
}

func (c *ServeCmd) Exec(args []string, conf *config.Config) error {
// no args
return startServer(conf)
}

func (c *ServeCmd) Usage() {
fmt.Fprintf(c.flagSet.Output(), " %s\t\tStart readflow server\n", cmdName)
}

func newServeCmd() cmd.Cmd {
c := &ServeCmd{
flagSet: flag.NewFlagSet(cmdName, flag.ExitOnError),
}
return c
}

func init() {
cmd.Add("serve", newServeCmd)
}
117 changes: 117 additions & 0 deletions cmd/serve/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package serve

import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"

"github.com/ncarlier/readflow/pkg/api"
"github.com/ncarlier/readflow/pkg/cache"
"github.com/ncarlier/readflow/pkg/config"
"github.com/ncarlier/readflow/pkg/db"
"github.com/ncarlier/readflow/pkg/exporter"
"github.com/ncarlier/readflow/pkg/exporter/pdf"
"github.com/ncarlier/readflow/pkg/metric"
"github.com/ncarlier/readflow/pkg/server"
"github.com/ncarlier/readflow/pkg/service"
"github.com/rs/zerolog/log"
)

func startServer(conf *config.Config) error {
log.Debug().Msg("starting readflow...")

// configure the DB
database, err := db.NewDB(conf.Database.URI)
if err != nil {
return fmt.Errorf("unable to configure the database: %w", err)
}

// configure download cache
downloadCache, err := cache.NewDefault("readflow-downloads")
if err != nil {
return fmt.Errorf("unable to configure the downloader cache storage: %w", err)
}

// configure the service registry
err = service.Configure(*conf, database, downloadCache)
if err != nil {
database.Close()
return fmt.Errorf("unable to configure the service registry: %w", err)
}

// register external exporters...
if conf.PDF.ServiceProvider != "" {
log.Info().Str("provider", conf.PDF.ServiceProvider).Msg("using PDF generator service")
exporter.Register("pdf", pdf.NewPDFExporter(conf.PDF.ServiceProvider))
}

// create HTTP server
httpServer := server.NewHTTPServer(conf)

// create and start metrics server
metricsServer := server.NewMetricsServer(conf)
if metricsServer != nil {
metric.StartCollectors(database)
go metricsServer.ListenAndServe()
}

// create and start SMTP server
smtpServer := server.NewSMTPHTTPServer(conf)
if smtpServer != nil {
go smtpServer.ListenAndServe()
}

done := make(chan bool)
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)

go func() {
<-quit
log.Debug().Msg("shutting down readflow...")
api.Shutdown()

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

if err := httpServer.Shutdown(ctx); err != nil {
log.Fatal().Err(err).Msg("unable to gracefully shutdown the HTTP server")
}
if smtpServer != nil {
if err := smtpServer.Shutdown(ctx); err != nil {
log.Fatal().Err(err).Msg("unable to gracefully shutdown the SMTP server")
}
}
if metricsServer != nil {
metric.StopCollectors()
if err := metricsServer.Shutdown(ctx); err != nil {
log.Fatal().Err(err).Msg("unable to gracefully shutdown the metrics server")
}
}

service.Shutdown()

if err := downloadCache.Close(); err != nil {
log.Error().Err(err).Msg("unable to gracefully shutdown the cache storage")
}

if err := database.Close(); err != nil {
log.Fatal().Err(err).Msg("could not gracefully shutdown database connection")
}

close(done)
}()

// set API health check as started
api.Start()

// start HTTP server
httpServer.ListenAndServe()

<-done
log.Debug().Msg("readflow stopped")

return nil
}
8 changes: 8 additions & 0 deletions cmd/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package cmd

import "github.com/ncarlier/readflow/pkg/config"

type Cmd interface {
Exec(args []string, conf *config.Config) error
Usage()
}
37 changes: 37 additions & 0 deletions cmd/version/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package initconfig

import (
"flag"
"fmt"

"github.com/ncarlier/readflow/cmd"
"github.com/ncarlier/readflow/pkg/config"
"github.com/ncarlier/readflow/pkg/version"
)

const cmdName = "version"

type VersionCmd struct {
flagSet *flag.FlagSet
}

func (c *VersionCmd) Exec(args []string, conf *config.Config) error {
// no args
version.Print()
return nil
}

func (c *VersionCmd) Usage() {
fmt.Fprintf(c.flagSet.Output(), " %s\tDisplay version\n", cmdName)
}

func newVersionCmd() cmd.Cmd {
c := &VersionCmd{
flagSet: flag.NewFlagSet(cmdName, flag.ExitOnError),
}
return c
}

func init() {
cmd.Add("version", newVersionCmd)
}
Loading
Loading