This commit is contained in:
Stanislav Nikitin 2019-10-22 04:38:40 +05:00
parent f5b1f9d9f9
commit 61d34f3687
No known key found for this signature in database
GPG Key ID: 106900B32F8192EE
11 changed files with 51 additions and 16 deletions

View File

@ -5,6 +5,8 @@ linters:
disable: disable:
# Actually not really needed. # Actually not really needed.
- gochecknoglobals - gochecknoglobals
# Well, it might help, but not so much.
- funlen
linters-settings: linters-settings:
lll: lll:
line-length: 420 line-length: 420

View File

@ -30,7 +30,9 @@ func main() {
// CTRL+C handler. // CTRL+C handler.
signalHandler := make(chan os.Signal, 1) signalHandler := make(chan os.Signal, 1)
shutdownDone := make(chan bool, 1) shutdownDone := make(chan bool, 1)
signal.Notify(signalHandler, os.Interrupt, syscall.SIGTERM) signal.Notify(signalHandler, os.Interrupt, syscall.SIGTERM)
go func() { go func() {
<-signalHandler <-signalHandler
log.Println("CTRL+C or SIGTERM received, shutting down gonewsd...") log.Println("CTRL+C or SIGTERM received, shutting down gonewsd...")

View File

@ -46,5 +46,6 @@ func addCapability(data interface{}) interface{} {
func handler(data interface{}) interface{} { func handler(data interface{}) interface{} {
caps := make([]string, len(capabilities)) caps := make([]string, len(capabilities))
copy(caps, capabilities) copy(caps, capabilities)
return caps return caps
} }

View File

@ -34,6 +34,7 @@ func Initialize() {
pathRaw = strings.Replace(pathRaw, "~", userHomeDir, 1) pathRaw = strings.Replace(pathRaw, "~", userHomeDir, 1)
} }
absPath, err1 := filepath.Abs(pathRaw) absPath, err1 := filepath.Abs(pathRaw)
if err1 != nil { if err1 != nil {
log.Fatalln("Failed to get absolute path for configuration file: " + err1.Error()) log.Fatalln("Failed to get absolute path for configuration file: " + err1.Error())
@ -46,6 +47,7 @@ func Initialize() {
} }
Cfg = &config{} Cfg = &config{}
err3 := yaml.Unmarshal(fileData, Cfg) err3 := yaml.Unmarshal(fileData, Cfg)
if err3 != nil { if err3 != nil {
log.Fatalln("Failed to parse configuration file: " + err3.Error()) log.Fatalln("Failed to parse configuration file: " + err3.Error())

View File

@ -47,6 +47,7 @@ func startConnectionWatcher() {
ticker.Stop() ticker.Stop()
log.Println("Connection watcher stopped and connection to database was shutted down") log.Println("Connection watcher stopped and connection to database was shutted down")
connWatcherStopped = true connWatcherStopped = true
} }
@ -56,11 +57,14 @@ func watcher() bool {
// If we're shutting down - stop connection watcher. // If we're shutting down - stop connection watcher.
if weAreShuttingDown { if weAreShuttingDown {
log.Println("Closing database connection...") log.Println("Closing database connection...")
err := Conn.Close() err := Conn.Close()
if err != nil { if err != nil {
log.Println("Failed to close database connection") log.Println("Failed to close database connection")
} }
Conn = nil Conn = nil
return true return true
} }

View File

@ -14,7 +14,7 @@ var (
Conn *sqlx.DB Conn *sqlx.DB
// Shutdown flags. // Shutdown flags.
// Sets to true when Shutdown() is called to indicate other subsystes // Sets to true when Shutdown() is called to indicate other subsystems
// that we're shutting down. // that we're shutting down.
weAreShuttingDown bool weAreShuttingDown bool
// Sets to true when connection watcher will be stopped. // Sets to true when connection watcher will be stopped.
@ -35,6 +35,7 @@ func Initialize() {
func Shutdown() { func Shutdown() {
weAreShuttingDown = true weAreShuttingDown = true
for { for {
if connWatcherStopped { if connWatcherStopped {
break break

View File

@ -11,21 +11,23 @@ import (
"github.com/pressly/goose" "github.com/pressly/goose"
) )
// Initialize initializes database migrations. This is the function
// where migrations should be registered.
func Initialize() { func Initialize() {
log.Println("Initializing database migrations...") log.Println("Initializing database migrations...")
_ = goose.SetDialect("postgres") _ = goose.SetDialect("postgres")
goose.AddNamedMigration("1_create_users_table.go", CreateUsersTableUp, CreateUsersTableDown) goose.AddNamedMigration("1_create_users_table.go", CreateUsersTableUp, CreateUsersTableDown)
// Migrations should be registered here.
} }
// Migrate parses environment for necessary parameters and starts
// database migration process.
func Migrate(db *sql.DB) { func Migrate(db *sql.DB) {
log.Println("Starting database migration procedure...") log.Println("Starting database migration procedure...")
// Prepare migrations configuration.
var action = "UP" var action = "UP"
actionFromEnv, actionFound := os.LookupEnv("DATABASE_ACTION") actionFromEnv, actionFound := os.LookupEnv("DATABASE_ACTION")
if actionFound { if actionFound {
log.Println("Migration action override: " + actionFromEnv) log.Println("Migration action override: " + actionFromEnv)
@ -35,13 +37,16 @@ func Migrate(db *sql.DB) {
} }
var count int64 var count int64
countFromEnv, countFound := os.LookupEnv("DATABASE_COUNT") countFromEnv, countFound := os.LookupEnv("DATABASE_COUNT")
if countFound { if countFound {
log.Println("Migration count override: " + countFromEnv) log.Println("Migration count override: " + countFromEnv)
countAsInt, err := strconv.ParseInt(countFromEnv, 10, 64) countAsInt, err := strconv.ParseInt(countFromEnv, 10, 64)
if err != nil { if err != nil {
log.Fatalln("Failed to convert count gathered from DATABASE_COUNT to integer") log.Fatalln("Failed to convert count gathered from DATABASE_COUNT to integer")
} }
count = countAsInt count = countAsInt
} else { } else {
log.Println("Applying or rollback this count of migrations: " + countFromEnv + ". 0 - all.") log.Println("Applying or rollback this count of migrations: " + countFromEnv + ". 0 - all.")
@ -49,27 +54,35 @@ func Migrate(db *sql.DB) {
// Execute migrations. // Execute migrations.
var err error var err error
currentDBVersion, gooseerr := goose.GetDBVersion(db) currentDBVersion, gooseerr := goose.GetDBVersion(db)
if gooseerr != nil { if gooseerr != nil {
log.Fatalln("Failed to get database version: " + gooseerr.Error()) log.Fatalln("Failed to get database version: " + gooseerr.Error())
} }
log.Println("Current database version obtained: " + strconv.Itoa(int(currentDBVersion))) log.Println("Current database version obtained: " + strconv.Itoa(int(currentDBVersion)))
if action == "UP" && count == 0 {
switch {
case action == "UP" && count == 0:
log.Println("Applying all unapplied migrations...") log.Println("Applying all unapplied migrations...")
err = goose.Up(db, ".") err = goose.Up(db, ".")
} else if action == "UP" && count != 0 { case action == "UP" && count != 0:
newVersion := currentDBVersion + count newVersion := currentDBVersion + count
log.Println("Migrating database to specific version: " + strconv.Itoa(int(newVersion))) log.Println("Migrating database to specific version: " + strconv.Itoa(int(newVersion)))
err = goose.UpTo(db, ".", newVersion) err = goose.UpTo(db, ".", newVersion)
} else if action == "DOWN" && count == 0 { case action == "DOWN" && count == 0:
log.Println("Downgrading database to zero state, you'll need to re-apply migrations!") log.Println("Downgrading database to zero state, you'll need to re-apply migrations!")
err = goose.Down(db, ".")
_ = goose.Down(db, ".")
log.Fatalln("Database downgraded to zero state. You have to re-apply migrations") log.Fatalln("Database downgraded to zero state. You have to re-apply migrations")
} else if action == "DOWN" && count != 0 { case action == "DOWN" && count != 0:
newVersion := currentDBVersion - count newVersion := currentDBVersion - count
log.Println("Downgrading database to specific version: " + strconv.Itoa(int(newVersion))) log.Println("Downgrading database to specific version: " + strconv.Itoa(int(newVersion)))
err = goose.DownTo(db, ".", newVersion) err = goose.DownTo(db, ".", newVersion)
} else { default:
log.Fatalln("Unsupported set of migration parameters, cannot continue: " + action + "/" + countFromEnv) log.Fatalln("Unsupported set of migration parameters, cannot continue: " + action + "/" + countFromEnv)
} }

View File

@ -117,6 +117,7 @@ func TestEventerLaunchNotExistingEvent(t *testing.T) {
if err == nil { if err == nil {
t.Fatal("LaunchEvent() returned empty error!") t.Fatal("LaunchEvent() returned empty error!")
} }
require.Nil(t, data) require.Nil(t, data)
Shutdown() Shutdown()

View File

@ -33,6 +33,7 @@ func Initialize() {
// all further events mapping changes. // all further events mapping changes.
func InitializeCompleted() { func InitializeCompleted() {
eventsInitialized = true eventsInitialized = true
log.Println("Events initialization completed") log.Println("Events initialization completed")
} }
@ -53,6 +54,7 @@ func LaunchEvent(eventName string, data interface{}) (interface{}, error) {
} }
returnedData := handler.Handler(data) returnedData := handler.Handler(data)
return returnedData, nil return returnedData, nil
} }

View File

@ -29,7 +29,7 @@ type connection struct {
// require start using two goroutines for handling connections, // require start using two goroutines for handling connections,
// one for writing and one for reading. // one for writing and one for reading.
transit bool transit bool
// Connection capabilites. // Connection capabilities.
capabilities []string capabilities []string
} }
@ -77,6 +77,7 @@ func (c *connection) Start() {
log.Println("Failed to write greeting for " + c.remoteAddr.String() + ": " + err.Error()) log.Println("Failed to write greeting for " + c.remoteAddr.String() + ": " + err.Error())
return return
} }
c.writer.Flush() c.writer.Flush()
// Start reading for commands. // Start reading for commands.
@ -120,8 +121,9 @@ func (c *connection) Start() {
} }
dataToWrite += ".\r\n" dataToWrite += ".\r\n"
c.writer.WriteString(dataToWrite) _, _ = c.writer.WriteString(dataToWrite)
c.writer.Flush() c.writer.Flush()
continue continue
} }
@ -129,8 +131,9 @@ func (c *connection) Start() {
if strings.ToLower(data[0]) == "mode" && strings.ToLower(data[1]) == "reader" { if strings.ToLower(data[0]) == "mode" && strings.ToLower(data[1]) == "reader" {
c.transit = false c.transit = false
// In any case we'll require user authentication for posting. // In any case we'll require user authentication for posting.
c.writer.WriteString("201 Posting prohibited\r\n") _, _ = c.writer.WriteString("201 Posting prohibited\r\n")
c.writer.Flush() _ = c.writer.Flush()
continue continue
} }
@ -149,7 +152,9 @@ func (c *connection) Start() {
log.Println("Failed to write string to socket for " + c.remoteAddr.String() + ": " + err.Error()) log.Println("Failed to write string to socket for " + c.remoteAddr.String() + ": " + err.Error())
break break
} }
c.writer.Flush()
_ = c.writer.Flush()
continue continue
} }
@ -161,7 +166,8 @@ func (c *connection) Start() {
log.Println("Failed to write string to socket for " + c.remoteAddr.String() + ": " + err1.Error()) log.Println("Failed to write string to socket for " + c.remoteAddr.String() + ": " + err1.Error())
break break
} }
c.writer.Flush()
_ = c.writer.Flush()
// Check for QUIT command. // Check for QUIT command.
if strings.ToLower(data[0]) == "quit" { if strings.ToLower(data[0]) == "quit" {

View File

@ -24,6 +24,7 @@ func startServer(config configuration.Network) {
if err != nil { if err != nil {
log.Fatalln("Failed to start TCP server on " + config.Address + ": " + err.Error()) log.Fatalln("Failed to start TCP server on " + config.Address + ": " + err.Error())
} }
defer func() { defer func() {
err := l.Close() err := l.Close()
if err != nil { if err != nil {