HW12 mutim storages
parent
47e7d8847e
commit
5c07ac5193
hw12_13_14_15_calendar
internal/storage
sql
src
app
config
logger
server/http
storage
|
@ -1,8 +1,8 @@
|
||||||
build:
|
build:
|
||||||
go build -o ./bin/calendar ./cmd/calendar
|
go build -o ./bin/calendar ./src
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test -race ./internal/... ./pkg/...
|
go test -race ./src/...
|
||||||
|
|
||||||
install-lint-deps:
|
install-lint-deps:
|
||||||
(which golangci-lint > /dev/null) || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
(which golangci-lint > /dev/null) || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.30.0
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package memorystorage
|
|
||||||
|
|
||||||
import "sync"
|
|
||||||
|
|
||||||
type Storage struct {
|
|
||||||
// TODO
|
|
||||||
mu sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func New() *Storage {
|
|
||||||
return &Storage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
|
|
@ -1,7 +0,0 @@
|
||||||
package memorystorage
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestStorage(t *testing.T) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
package sqlstorage
|
|
||||||
|
|
||||||
import "context"
|
|
||||||
|
|
||||||
type Storage struct {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
func New() *Storage {
|
|
||||||
return &Storage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) Connect(ctx context.Context) error {
|
|
||||||
// TODO
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Storage) Close(ctx context.Context) error {
|
|
||||||
// TODO
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -7,28 +7,32 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Logger struct{
|
Logger struct {
|
||||||
File string
|
File string
|
||||||
Level string
|
Level string
|
||||||
MuteStdout bool
|
MuteStdout bool
|
||||||
}
|
}
|
||||||
Storage struct {
|
Storage struct {
|
||||||
In_memory bool
|
In_memory bool
|
||||||
Sql_host string
|
Sql_host string
|
||||||
Sql_port string
|
Sql_port string
|
||||||
Sql_dbase string
|
Sql_dbase string
|
||||||
Sql_user string
|
Sql_user string
|
||||||
Sql_pass string
|
Sql_pass string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confita может быти и хороша, но она не возвращает ошибки, если не может распарсить файл в структуру. Мне не нравится такая "молчаливость"
|
// Confita может быти и хороша, но она не возвращает ошибки, если не может распарсить файл в структуру. Мне не нравится такая "молчаливость"
|
||||||
func NewConfig(configFile string) (Config, error) {
|
func NewConfig(configFile string) (Config, error) {
|
||||||
f,err:= os.Open(configFile)
|
f, err := os.Open(configFile)
|
||||||
if err != nil {return Config{}, err}
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
s,err := ioutil.ReadAll(f)
|
s, err := ioutil.ReadAll(f)
|
||||||
if err != nil {return Config{}, err}
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
var config Config
|
var config Config
|
||||||
_, err = toml.Decode(string(s), &config)
|
_, err = toml.Decode(string(s), &config)
|
||||||
return config, err
|
return config, err
|
|
@ -16,7 +16,9 @@ var _ = func() bool {
|
||||||
func TestNewConfig(t *testing.T) {
|
func TestNewConfig(t *testing.T) {
|
||||||
|
|
||||||
badfile, err := ioutil.TempFile("", "conf.")
|
badfile, err := ioutil.TempFile("", "conf.")
|
||||||
if err != nil { oslog.Fatal(err) }
|
if err != nil {
|
||||||
|
oslog.Fatal(err)
|
||||||
|
}
|
||||||
defer os.Remove(badfile.Name())
|
defer os.Remove(badfile.Name())
|
||||||
badfile.WriteString(`aefSD
|
badfile.WriteString(`aefSD
|
||||||
sadfg
|
sadfg
|
||||||
|
@ -25,7 +27,9 @@ V`)
|
||||||
badfile.Sync()
|
badfile.Sync()
|
||||||
|
|
||||||
goodfile, err := ioutil.TempFile("", "conf.")
|
goodfile, err := ioutil.TempFile("", "conf.")
|
||||||
if err != nil { oslog.Fatal(err) }
|
if err != nil {
|
||||||
|
oslog.Fatal(err)
|
||||||
|
}
|
||||||
defer os.Remove(goodfile.Name())
|
defer os.Remove(goodfile.Name())
|
||||||
goodfile.WriteString(`[storage]
|
goodfile.WriteString(`[storage]
|
||||||
in_memory = true
|
in_memory = true
|
||||||
|
@ -33,22 +37,22 @@ sql_host = "localhost"`)
|
||||||
goodfile.Sync()
|
goodfile.Sync()
|
||||||
|
|
||||||
t.Run("No such file", func(t *testing.T) {
|
t.Run("No such file", func(t *testing.T) {
|
||||||
c,e := NewConfig("adfergdth")
|
c, e := NewConfig("adfergdth")
|
||||||
require.Equal(t,Config{},c)
|
require.Equal(t, Config{}, c)
|
||||||
require.Error(t,e)
|
require.Error(t, e)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Bad file", func(t *testing.T) {
|
t.Run("Bad file", func(t *testing.T) {
|
||||||
c,e := NewConfig(badfile.Name())
|
c, e := NewConfig(badfile.Name())
|
||||||
require.Equal(t,Config{},c)
|
require.Equal(t, Config{}, c)
|
||||||
require.Error(t,e)
|
require.Error(t, e)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("TOML reading", func(t *testing.T) {
|
t.Run("TOML reading", func(t *testing.T) {
|
||||||
c,e := NewConfig(goodfile.Name())
|
c, e := NewConfig(goodfile.Name())
|
||||||
require.Equal(t,true,c.Storage.In_memory)
|
require.Equal(t, true, c.Storage.In_memory)
|
||||||
require.Equal(t,"localhost",c.Storage.Sql_host)
|
require.Equal(t, "localhost", c.Storage.Sql_host)
|
||||||
require.NoError(t,e)
|
require.NoError(t, e)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ package logger
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
amitralog "github.com/amitrai48/logger"
|
amitralog "github.com/amitrai48/logger"
|
||||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config"
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/config"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -23,7 +23,7 @@ type Log struct {
|
||||||
|
|
||||||
func New(conf config.Config) (Log, error) {
|
func New(conf config.Config) (Log, error) {
|
||||||
|
|
||||||
if conf.Logger.File=="" || !validLevel(conf.Logger.Level) {
|
if conf.Logger.File == "" || !validLevel(conf.Logger.Level) {
|
||||||
return Log{}, errors.New("invalid logger config")
|
return Log{}, errors.New("invalid logger config")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ func (l *Log) Fatal(format string, args ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func validLevel(level string) bool {
|
func validLevel(level string) bool {
|
||||||
l := []string{"debug","info","warn","error","fatal"}
|
l := []string{"debug", "info", "warn", "error", "fatal"}
|
||||||
for _,v:=range l {
|
for _, v := range l {
|
||||||
if strings.ToLower(level)==v {
|
if strings.ToLower(level) == v {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config"
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/config"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
oslog "log"
|
oslog "log"
|
||||||
"os"
|
"os"
|
||||||
|
@ -12,7 +12,9 @@ import (
|
||||||
|
|
||||||
func TestLoggerLogic(t *testing.T) {
|
func TestLoggerLogic(t *testing.T) {
|
||||||
tmpfile, err := ioutil.TempFile("", "log.")
|
tmpfile, err := ioutil.TempFile("", "log.")
|
||||||
if err != nil { oslog.Fatal(err) }
|
if err != nil {
|
||||||
|
oslog.Fatal(err)
|
||||||
|
}
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
conf := config.Config{Logger: struct {
|
conf := config.Config{Logger: struct {
|
||||||
|
@ -21,16 +23,20 @@ func TestLoggerLogic(t *testing.T) {
|
||||||
MuteStdout bool
|
MuteStdout bool
|
||||||
}{File: tmpfile.Name(), Level: "warn", MuteStdout: false}}
|
}{File: tmpfile.Name(), Level: "warn", MuteStdout: false}}
|
||||||
log, err := New(conf)
|
log, err := New(conf)
|
||||||
if err != nil { oslog.Fatal(err) }
|
if err != nil {
|
||||||
|
oslog.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
t.Run("Messages arround the level", func(t *testing.T) {
|
t.Run("Messages arround the level", func(t *testing.T) {
|
||||||
log.Debug("debug message")
|
log.Debug("debug message")
|
||||||
log.Error("error message")
|
log.Error("error message")
|
||||||
|
|
||||||
res,err := ioutil.ReadAll(tmpfile)
|
res, err := ioutil.ReadAll(tmpfile)
|
||||||
if err != nil { oslog.Fatal(err) }
|
if err != nil {
|
||||||
require.Less(t,strings.Index(string(res),"debug message"),0)
|
oslog.Fatal(err)
|
||||||
require.Greater(t,strings.Index(string(res),"error message"),0)
|
}
|
||||||
|
require.Less(t, strings.Index(string(res), "debug message"), 0)
|
||||||
|
require.Greater(t, strings.Index(string(res), "error message"), 0)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +48,7 @@ func TestLoggerNegative(t *testing.T) {
|
||||||
MuteStdout bool
|
MuteStdout bool
|
||||||
}{File: "", Level: "debug", MuteStdout: true}}
|
}{File: "", Level: "debug", MuteStdout: true}}
|
||||||
_, err := New(conf)
|
_, err := New(conf)
|
||||||
require.Error(t,err, "invalid logger config")
|
require.Error(t, err, "invalid logger config")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Bad level", func(t *testing.T) {
|
t.Run("Bad level", func(t *testing.T) {
|
||||||
|
@ -52,6 +58,6 @@ func TestLoggerNegative(t *testing.T) {
|
||||||
MuteStdout bool
|
MuteStdout bool
|
||||||
}{File: "asdafad", Level: "wegretryjt", MuteStdout: true}}
|
}{File: "asdafad", Level: "wegretryjt", MuteStdout: true}}
|
||||||
_, err := New(conf)
|
_, err := New(conf)
|
||||||
require.Error(t,err,"invalid logger config")
|
require.Error(t, err, "invalid logger config")
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -2,14 +2,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/app"
|
||||||
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/config"
|
||||||
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/logger"
|
||||||
|
internalhttp "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/server/http"
|
||||||
|
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage"
|
||||||
oslog "log"
|
oslog "log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config"
|
|
||||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/app"
|
|
||||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/logger"
|
|
||||||
internalhttp "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/server/http"
|
|
||||||
memorystorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/memory"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var configFile string
|
var configFile string
|
||||||
|
@ -21,13 +21,21 @@ func init() {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
conf, err := config.NewConfig(configFile)
|
conf, err := config.NewConfig(configFile)
|
||||||
if err != nil { oslog.Fatal("не удалось открыть файл конфигурации:", err.Error())}
|
if err != nil {
|
||||||
|
oslog.Fatal("не удалось открыть файл конфигурации:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
log, err := logger.New(conf)
|
log, err := logger.New(conf)
|
||||||
if err != nil { oslog.Fatal("не удалось запустить логер:", err.Error())}
|
if err != nil {
|
||||||
|
oslog.Fatal("не удалось запустить логер:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
storage := memorystorage.New()
|
st := store.NewStore(conf)
|
||||||
calendar := app.New(log, storage)
|
if err != nil {
|
||||||
|
oslog.Fatal("не удалось инициализировать хранилище:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
calendar := app.New(log, st)
|
||||||
|
|
||||||
server := internalhttp.NewServer(calendar)
|
server := internalhttp.NewServer(calendar)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package storage
|
package event
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
ID string
|
ID string
|
||||||
Title string
|
Title string
|
||||||
// TODO
|
Date string
|
||||||
}
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package memorystorage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/event"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Storage struct {
|
||||||
|
events []event.Event
|
||||||
|
mu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Storage {
|
||||||
|
return &Storage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Save(event event.Event) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Update(event event.Event) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Delete(event event.Event) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) List() []event.Event {
|
||||||
|
return []event.Event{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Get(id string) (event.Event, bool) {
|
||||||
|
return event.Event{}, false
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package sqlstorage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/event"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Storage struct {
|
||||||
|
Events []event.Event
|
||||||
|
Mu sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Storage {
|
||||||
|
return &Storage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Storage) Connect(ctx context.Context) error {
|
||||||
|
// TODO
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Storage) Close(ctx context.Context) error {
|
||||||
|
// TODO
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Save(e event.Event) error {
|
||||||
|
if _, ok := s.Get(e.ID); !ok {
|
||||||
|
s.Mu.Lock()
|
||||||
|
s.Events = append(s.Events, e)
|
||||||
|
s.Mu.Unlock()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Update(event event.Event) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Delete(event event.Event) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) List() []event.Event {
|
||||||
|
return []event.Event{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Storage) Get(id string) (event.Event, bool) {
|
||||||
|
return event.Event{}, false
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/config"
|
||||||
|
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/event"
|
||||||
|
memorystorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/memory"
|
||||||
|
sqlstorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StoreInterface interface {
|
||||||
|
Save(event event.Event) error
|
||||||
|
Update(event event.Event) error
|
||||||
|
Delete(event event.Event) error
|
||||||
|
List() []event.Event
|
||||||
|
Get(id string) (event.Event, bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStore(config config.Config) StoreInterface {
|
||||||
|
if config.Storage.In_memory {
|
||||||
|
st := memorystorage.New()
|
||||||
|
return st
|
||||||
|
}
|
||||||
|
return sqlstorage.New()
|
||||||
|
}
|
Loading…
Reference in New Issue