-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
moved all website startup fixes and repairs to the "fix" command.
- Loading branch information
1 parent
bbb0e45
commit 8fe26e1
Showing
7 changed files
with
216 additions
and
186 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,11 +19,12 @@ import ( | |
) | ||
|
||
const ( | ||
Title = "Defacto2 web application" // Title of this program. | ||
Domain = "defacto2.net" // Domain of the website. | ||
Program = "defacto2-server" // Program is the command line name of this program. | ||
Author = "Ben Garrett" // Author is the primary programmer of this program. | ||
Email = "[email protected]" // Email contact for public display. | ||
Title = "Defacto2 web application" // Title of this program. | ||
Domain = "defacto2.net" // Domain of the website. | ||
Program = "defacto2-server" // Program is the command line name of this program. | ||
Author = "Ben Garrett" // Author is the primary programmer of this program. | ||
Email = "[email protected]" // Email contact for public display. | ||
RecentYear = 2024 // Most recent year of compilation for this program. | ||
) | ||
|
||
var ErrCmd = errors.New("cannot run command as config is nil") | ||
|
@@ -35,12 +36,11 @@ func App(ver string, c *config.Config) *cli.App { | |
Name: Title, | ||
Version: Version(ver), | ||
Usage: "serve the Defacto2 web site", | ||
UsageText: "defacto2-server" + | ||
"\ndefacto2-server [command]" + | ||
"\ndefacto2-server [command] --help" + | ||
"\ndefacto2-server [flag]", | ||
UsageText: Program + | ||
"\n" + Program + " [command]" + | ||
"\n" + Program + " [command] --help" + | ||
"\n" + Program + " [flag]", | ||
Description: desc(c), | ||
Compiled: versioninfo.LastCommit, | ||
Copyright: Copyright(), | ||
HelpName: Program, | ||
Authors: []*cli.Author{ | ||
|
@@ -50,13 +50,28 @@ func App(ver string, c *config.Config) *cli.App { | |
}, | ||
}, | ||
Commands: []*cli.Command{ | ||
Config(c), | ||
Address(c), | ||
Config(c), Address(c), Fix(c), | ||
}, | ||
} | ||
return app | ||
} | ||
|
||
// Fix is the `fix` command help and action. | ||
func Fix(c *config.Config) *cli.Command { | ||
return &cli.Command{ | ||
Name: "fix", | ||
Aliases: []string{"f"}, | ||
Usage: "fix the database and assets", | ||
Description: "Fix the database entries and file assets by running scans and checks.", | ||
Action: func(_ *cli.Context) error { | ||
if err := c.Fixer(); err != nil { | ||
return fmt.Errorf("command fix: %w", err) | ||
} | ||
return nil | ||
}, | ||
} | ||
} | ||
|
||
// Address is the `address` command help and action. | ||
func Address(c *config.Config) *cli.Command { | ||
return &cli.Command{ | ||
|
@@ -120,10 +135,6 @@ func Commit(ver string) string { | |
} else if s != "" { | ||
x = append(x, s) | ||
} | ||
built := "built at" | ||
if l := LastCommit(); l != "" && !strings.Contains(ver, built) { | ||
x = append(x, built+" "+l) | ||
} | ||
if len(x) == 0 || x[0] == "devel" { | ||
return "n/a (not a build)" | ||
} | ||
|
@@ -135,23 +146,14 @@ func Commit(ver string) string { | |
func Copyright() string { | ||
const initYear = 2023 | ||
years := strconv.Itoa(initYear) | ||
t := versioninfo.LastCommit | ||
if t.Year() > initYear { | ||
years += "-" + t.Local().Format("06") //nolint:gosmopolitan | ||
if RecentYear > initYear { | ||
const endDigits = RecentYear % 100 | ||
years += "-" + strconv.Itoa(endDigits) | ||
} | ||
s := fmt.Sprintf("© %s Defacto2 & %s", years, Author) | ||
return s | ||
} | ||
|
||
// LastCommit returns the date of the last repository commit. | ||
func LastCommit() string { | ||
d := versioninfo.LastCommit | ||
if d.IsZero() { | ||
return "" | ||
} | ||
return d.Local().Format("2006 Jan 2 15:04") //nolint:gosmopolitan | ||
} | ||
|
||
// OS returns the program operating system. | ||
func OS() string { | ||
t := cases.Title(language.English) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package config | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/Defacto2/server/internal/command" | ||
"github.com/Defacto2/server/internal/helper" | ||
"github.com/Defacto2/server/internal/postgres" | ||
"github.com/Defacto2/server/internal/zaplog" | ||
"github.com/Defacto2/server/model/fix" | ||
) | ||
|
||
// Fixer is used to fix any known issues with the file assets and the database entries. | ||
func (c Config) Fixer() error { | ||
logger := zaplog.Timestamp().Sugar() | ||
db, err := postgres.Open() | ||
if err != nil { | ||
logger.Errorf("fix could not initialize the database data: %s", err) | ||
} | ||
defer db.Close() | ||
var database postgres.Version | ||
if err := database.Query(db); err != nil { | ||
logger.Errorf("postgres version query: %w", err) | ||
} | ||
fmt.Fprintf(os.Stdout, "\n%+v\n", c) | ||
ctx := context.WithValue(context.Background(), helper.LoggerKey, logger) | ||
count := RecordCount(ctx, db) | ||
const welcome = "Defacto2 web application" | ||
switch { | ||
case count == 0: | ||
logger.Error(welcome + " with no database records") | ||
case MinimumFiles > count: | ||
logger.Warnf(welcome+" with only %d records, expecting at least %d+", count, MinimumFiles) | ||
default: | ||
logger.Infof(welcome+" using %d records", count) | ||
} | ||
c.repairer(ctx, db) | ||
c.sanityChecks(ctx) | ||
SanityTmpDir() | ||
return nil | ||
} | ||
|
||
// repairer is used to fix any known issues with the file assets and the database entries. | ||
// These are skipped if the Production mode environment variable is set to false. | ||
func (c Config) repairer(ctx context.Context, db *sql.DB) { | ||
if db == nil { | ||
panic(fmt.Errorf("%w: repairer", ErrPointer)) | ||
} | ||
logger := helper.Logger(ctx) | ||
if err := c.RepairAssets(ctx, db); err != nil { | ||
logger.Errorf("asset repairs: %s", err) | ||
} | ||
if err := repairDatabase(ctx, db); err != nil { | ||
if errors.Is(err, ErrVer) { | ||
logger.Warnf("A %s, is the database server down?", ErrVer) | ||
} | ||
logger.Errorf("repair database could not initialize the database data: %s", err) | ||
} | ||
} | ||
|
||
// repairDatabase on startup checks the database connection and make any data corrections. | ||
func repairDatabase(ctx context.Context, db *sql.DB) error { | ||
if db == nil { | ||
panic(fmt.Errorf("%w: repair database", ErrPointer)) | ||
} | ||
tx, err := db.Begin() | ||
if err != nil { | ||
return fmt.Errorf("repair database could not begin a transaction: %w", err) | ||
} | ||
if err := fix.Artifacts.Run(ctx, db, tx); err != nil { | ||
defer func() { | ||
if err := tx.Rollback(); err != nil { | ||
logger := helper.Logger(ctx) | ||
logger.Error(err) | ||
} | ||
}() | ||
return fmt.Errorf("repair database could not fix all artifacts: %w", err) | ||
} | ||
return nil | ||
} | ||
|
||
// sanityChecks is used to perform a number of sanity checks on the file assets and database. | ||
// These are skipped if the Production mode environment variable is set.to false. | ||
func (c Config) sanityChecks(ctx context.Context) { | ||
logger := helper.Logger(ctx) | ||
if err := c.Checks(logger); err != nil { | ||
logger.Errorf("sanity checks could not read the environment variable, "+ | ||
"it probably contains an invalid value: %s", err) | ||
} | ||
cmdChecks(ctx) | ||
conn, err := postgres.New() | ||
if err != nil { | ||
logger.Errorf("sanity checks could not initialize the database data: %s", err) | ||
return | ||
} | ||
if err := conn.Validate(logger); err != nil { | ||
panic(fmt.Errorf("sanity check conn validate: %w", err)) | ||
} | ||
} | ||
|
||
// checks is used to confirm the required commands are available. | ||
// These are skipped if readonly is true. | ||
func cmdChecks(ctx context.Context) { | ||
logger := helper.Logger(ctx) | ||
var buf strings.Builder | ||
for i, name := range command.Lookups() { | ||
if err := command.LookCmd(name); err != nil { | ||
buf.WriteString("\n\t\t\tmissing: " + name) | ||
buf.WriteString("\t" + command.Infos()[i]) | ||
} | ||
} | ||
if buf.Len() > 0 { | ||
logger.Warnln("The following commands are required for the server to run in WRITE MODE", | ||
"\n\t\t\tThese need to be installed and accessible on the system path:"+ | ||
"\t\t\t"+buf.String()) | ||
} | ||
if err := command.LookupUnrar(); err != nil { | ||
if errors.Is(err, command.ErrVers) { | ||
logger.Warnf("Found unrar but " + | ||
"could not find unrar by Alexander Roshal, " + | ||
"is unrar-free mistakenly installed?") | ||
return | ||
} | ||
logger.Warnf("lookup unrar check: %s", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.