HW12 реализовал вроде бы все, что нужно

pull/13/head
Andrey Ivanov 2020-09-24 16:10:24 +03:00 committed by Andrey Ivanov
parent 96a69e9833
commit 1fe653c9bd
20 changed files with 278 additions and 188 deletions

View File

@ -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

View File

@ -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

View File

@ -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
)

View File

@ -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)
})
}

View File

@ -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 {

View File

@ -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"

View File

@ -0,0 +1,9 @@
package http
/*
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
})
}
*/

View File

@ -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
}

View File

@ -1,7 +1,6 @@
package event
type Event struct {
ID string
Title string
Date string
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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!"))
}

View File

@ -1,7 +0,0 @@
package internalhttp
//func loggingMiddleware(next http.Handler) http.Handler {
// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// TODO
// })
//}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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
}