HW12 реализовал вроде бы все, что нужно
parent
96a69e9833
commit
1fe653c9bd
|
@ -2,15 +2,15 @@ build:
|
|||
go build -o ./bin/calendar ./src
|
||||
|
||||
run:
|
||||
go run ./src/calendar/main.go -config ./configs/config.toml
|
||||
go run ./cmd/calendar/main.go -config ./configs/config.toml
|
||||
|
||||
test:
|
||||
go test -race ./src/...
|
||||
go test -race ./internal/...
|
||||
|
||||
lint: install-lint-deps
|
||||
golangci-lint run ./...
|
||||
golangci-lint run .cmd/... ./internal/...
|
||||
|
||||
install-lint-deps:
|
||||
go install github.com/golangci/golangci-lint/cmd/golangci-lint
|
||||
(which golangci-lint > /dev/null) || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.30.0
|
||||
|
||||
.PHONY: build run test lint
|
|
@ -6,11 +6,12 @@ import (
|
|||
"os"
|
||||
"os/signal"
|
||||
|
||||
"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"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"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/config"
|
||||
"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"
|
||||
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage"
|
||||
)
|
||||
|
||||
var configFile string
|
|
@ -5,8 +5,9 @@ go 1.14
|
|||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/amitrai48/logger v0.0.0-20190214092904-448001c055ec
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/mattn/go-shellwords v1.0.10 // indirect
|
||||
github.com/stretchr/testify v1.4.0
|
||||
go.uber.org/zap v1.15.0
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5
|
||||
go.uber.org/zap v1.15.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
)
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/logger"
|
||||
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage"
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
CreateEvent(ctx context.Context, title string) (err error)
|
||||
Handler(w http.ResponseWriter, r *http.Request)
|
||||
LoggingMiddleware(next http.HandlerFunc) http.HandlerFunc
|
||||
}
|
||||
|
||||
type App struct {
|
||||
Storage store.StorageInterface
|
||||
Logger logger.Interface
|
||||
}
|
||||
|
||||
func New(logger logger.Interface, storage store.StorageInterface) *App {
|
||||
return &App{Logger: logger, Storage: storage}
|
||||
}
|
||||
|
||||
func (a *App) CreateEvent(ctx context.Context, title string) (err error) {
|
||||
_, err = a.Storage.Create(event.Event{Title: title})
|
||||
if err != nil {
|
||||
a.Logger.Errorf("can not create event")
|
||||
}
|
||||
a.Logger.Infof("event created")
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *App) Handler(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
_, _ = w.Write([]byte("Hello! I'm calendar app!"))
|
||||
}
|
||||
|
||||
func (a *App) LoggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
a.Logger.Infof("receive %s request from IP %s", r.Method, r.RemoteAddr)
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
amitralog "github.com/amitrai48/logger"
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/config"
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config"
|
||||
)
|
||||
|
||||
type Interface interface {
|
|
@ -2,7 +2,7 @@ package logger
|
|||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/config"
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config"
|
||||
"io/ioutil"
|
||||
oslog "log"
|
||||
"os"
|
|
@ -0,0 +1,9 @@
|
|||
package http
|
||||
|
||||
/*
|
||||
func loggingMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
})
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,37 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/app"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
server *http.Server
|
||||
app app.App
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewServer(app *app.App, address string, port string) *Server {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &Server{server: &http.Server{Addr: net.JoinHostPort(address, port), Handler: app.LoggingMiddleware(app.Handler)}, app: *app, ctx: ctx, cancel: cancel}
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
if err := s.server.ListenAndServe(); err != nil {
|
||||
return err
|
||||
}
|
||||
s.app.Logger.Infof("Server starting")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Stop() error {
|
||||
if err := s.server.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
s.app.Logger.Infof("Server starting")
|
||||
return nil
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package event
|
||||
|
||||
type Event struct {
|
||||
ID string
|
||||
Title string
|
||||
Date string
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package memorystorage
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event"
|
||||
)
|
||||
|
||||
type Storage struct {
|
||||
Events map[int64]event.Event
|
||||
lastID int64
|
||||
Mu sync.RWMutex
|
||||
}
|
||||
|
||||
func New() *Storage {
|
||||
return &Storage{}
|
||||
}
|
||||
|
||||
func (s *Storage) Create(event event.Event) (int64, error) {
|
||||
s.Mu.Lock()
|
||||
s.lastID++
|
||||
s.Events[s.lastID] = event
|
||||
s.Mu.Unlock()
|
||||
return s.lastID, nil
|
||||
}
|
||||
|
||||
func (s *Storage) Update(id int64, event event.Event) error {
|
||||
s.Mu.Lock()
|
||||
s.Events[id] = event
|
||||
s.Mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Storage) Delete(id int64) error {
|
||||
s.Mu.Lock()
|
||||
delete(s.Events, id)
|
||||
s.Mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Storage) List() (map[int64]event.Event, error) {
|
||||
return s.Events, nil
|
||||
}
|
||||
|
||||
func (s *Storage) GetByID(id int64) (event.Event, bool) {
|
||||
if s.Events[id].Title == "" {
|
||||
return event.Event{}, false
|
||||
}
|
||||
return s.Events[id], false
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package sqlstorage
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
User string
|
||||
Pass string
|
||||
Host string
|
||||
Port string
|
||||
Dbase string
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func New(conf Config) *Storage {
|
||||
return &Storage{}
|
||||
}
|
||||
|
||||
func (s *Storage) Connect(config Config) error {
|
||||
var err error
|
||||
s.db, err = sql.Open("mysql", config.User+":"+config.Pass+"@tcp("+config.Host+":"+config.Port+")/"+config.Dbase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Storage) Close() error {
|
||||
return s.db.Close()
|
||||
}
|
||||
|
||||
func (s *Storage) Create(event event.Event) (int64, error) {
|
||||
res, err := s.db.Exec(
|
||||
`INSERT INTO events (title, date) VALUES ($1, $2)`,
|
||||
event.Title,
|
||||
event.Date,
|
||||
)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
return res.LastInsertId()
|
||||
}
|
||||
|
||||
func (s *Storage) Update(id int64, event event.Event) error {
|
||||
_, err := s.db.Exec(
|
||||
`UPDATE events set title=$1, date=$2 where id=$3`,
|
||||
event.Title,
|
||||
event.Date,
|
||||
id,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Storage) Delete(id int64) error {
|
||||
_, err := s.db.Exec(
|
||||
`DELETE from events where id=$1`,
|
||||
id,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Storage) List() (map[int64]event.Event, error) {
|
||||
res := make(map[int64]event.Event)
|
||||
results, err := s.db.Query(
|
||||
`SELECT (id,title,date) from events ORDER BY id`)
|
||||
if err != nil || results.Err() != nil {
|
||||
return res, err
|
||||
}
|
||||
defer results.Close()
|
||||
for results.Next() {
|
||||
var tmp struct {
|
||||
id int64
|
||||
title string
|
||||
date string
|
||||
}
|
||||
err = results.Scan(&tmp.id, &tmp.title, &tmp.date)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res[tmp.id] = event.Event{Title: tmp.title, Date: tmp.date}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *Storage) GetByID(id int64) (event.Event, bool) {
|
||||
var res event.Event
|
||||
err := s.db.QueryRow(
|
||||
`SELECT (title,date) from events where id=$1`, id).Scan(res.Title, res.Date)
|
||||
if err != nil {
|
||||
return res, false
|
||||
}
|
||||
return res, true
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"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"
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event"
|
||||
memorystorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/memory"
|
||||
sqlstorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/sql"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
|
@ -16,11 +16,11 @@ type Config struct {
|
|||
}
|
||||
|
||||
type StorageInterface interface {
|
||||
Create(event event.Event) error
|
||||
Update(event event.Event) error
|
||||
Delete(event event.Event) error
|
||||
List() []event.Event
|
||||
Get(id string) (event.Event, bool)
|
||||
Create(event event.Event) (int64, error)
|
||||
Update(id int64, event event.Event) error
|
||||
Delete(id int64) error
|
||||
List() (map[int64]event.Event, error)
|
||||
GetByID(id int64) (event.Event, bool)
|
||||
}
|
||||
|
||||
func NewStore(conf Config) StorageInterface {
|
|
@ -0,0 +1,14 @@
|
|||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE events (
|
||||
id int(16) NOT NULL AUTO_INCREMENT,
|
||||
title varchar(255) NOT NULL,
|
||||
date varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE events;
|
||||
-- +goose StatementEnd
|
|
@ -1,38 +0,0 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/logger"
|
||||
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage"
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/event"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
CreateEvent(ctx context.Context, id string, title string) (err error)
|
||||
Handler(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
type App struct {
|
||||
storage store.StorageInterface
|
||||
logger logger.Interface
|
||||
}
|
||||
|
||||
func New(logger logger.Interface, storage store.StorageInterface) *App {
|
||||
return &App{logger: logger, storage: storage}
|
||||
}
|
||||
|
||||
func (a *App) CreateEvent(ctx context.Context, id string, title string) (err error) {
|
||||
err = a.storage.Create(event.Event{ID: id, Title: title})
|
||||
if err != nil {
|
||||
a.logger.Errorf("can not create event")
|
||||
}
|
||||
a.logger.Infof("event created")
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *App) Handler(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
_, _ = w.Write([]byte("Hello! I'm calendar app!"))
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package internalhttp
|
||||
|
||||
//func loggingMiddleware(next http.Handler) http.Handler {
|
||||
// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO
|
||||
// })
|
||||
//}
|
|
@ -1,25 +0,0 @@
|
|||
package internalhttp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/app"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
server *http.Server
|
||||
app app.Interface
|
||||
}
|
||||
|
||||
func NewServer(app app.Interface, address string, port string) *Server {
|
||||
return &Server{server: &http.Server{Addr: net.JoinHostPort(address, port), Handler: http.HandlerFunc(app.Handler)}, app: app}
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
return s.server.ListenAndServe()
|
||||
}
|
||||
|
||||
func (s *Server) Stop() error {
|
||||
return s.server.Close()
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package memorystorage
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/event"
|
||||
)
|
||||
|
||||
type Storage struct {
|
||||
Events []event.Event
|
||||
Mu sync.RWMutex
|
||||
}
|
||||
|
||||
func New() *Storage {
|
||||
return &Storage{}
|
||||
}
|
||||
|
||||
func (s *Storage) Create(event event.Event) error {
|
||||
if _, ok := s.Get(event.ID); !ok {
|
||||
s.Mu.Lock()
|
||||
s.Events = append(s.Events, event)
|
||||
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
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package sqlstorage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/src/storage/event"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Host string
|
||||
Port string
|
||||
Dbase string
|
||||
User string
|
||||
Pass string
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
//Events []event.Event
|
||||
//Mu sync.RWMutex
|
||||
}
|
||||
|
||||
func New(conf Config) *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) Create(e event.Event) error {
|
||||
// TODO
|
||||
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
|
||||
}
|
Loading…
Reference in New Issue