HW12 completed

pull/13/head
Andrey Ivanov 2020-09-25 11:20:26 +03:00 committed by Andrey Ivanov
parent acc97b1ac9
commit 73a669ab90
9 changed files with 136 additions and 91 deletions

View File

@ -3,6 +3,7 @@ package app
import ( import (
"context" "context"
"net/http" "net/http"
"time"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/logger" "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" store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage"
@ -40,7 +41,18 @@ func (a *App) Handler(w http.ResponseWriter, r *http.Request) {
func (a *App) LoggingMiddleware(next http.HandlerFunc) http.HandlerFunc { func (a *App) LoggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
a.Logger.Infof("receive %s request from IP %s", r.Method, r.RemoteAddr) start := time.Now()
defer func() {
var path, useragent string
if r.URL != nil {
path = r.URL.Path
}
if len(r.UserAgent()) > 0 {
useragent = r.UserAgent()
}
latency := time.Since(start)
a.Logger.Infof("receive %s request from IP: %s on path: %s, duration: %s useragent: %s ", r.Method, r.RemoteAddr, path, latency, useragent)
}()
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }

View File

@ -66,11 +66,6 @@ func (l *Logger) Fatalf(format string, args ...interface{}) {
} }
func validLevel(level string) bool { func validLevel(level string) bool {
l := []string{"debug", "info", "warn", "error", "fatal"} var l = map[string]int{"debug": 1, "info": 1, "warn": 1, "error": 1, "fatal": 1}
for _, v := range l { return l[strings.ToLower(level)] == 1
if strings.ToLower(level) == v {
return true
}
}
return false
} }

View File

@ -1,7 +1,6 @@
package http package http
import ( import (
"context"
"net" "net"
"net/http" "net/http"
@ -11,13 +10,10 @@ import (
type Server struct { type Server struct {
server *http.Server server *http.Server
app app.App app app.App
ctx context.Context
cancel context.CancelFunc
} }
func NewServer(app *app.App, address string, port string) *Server { 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}
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 { func (s *Server) Start() error {

View File

@ -1,6 +1,14 @@
package event package event
import (
"time"
)
type Event struct { type Event struct {
Title string Title string
Date string Date time.Time
Latency time.Duration
Note string
UserID int64
NotifyTime time.Duration
} }

View File

@ -1,4 +1,4 @@
package memorystorage package memory
import ( import (
"sync" "sync"

View File

@ -0,0 +1,60 @@
package memory
import (
"github.com/stretchr/testify/require"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event"
"testing"
"time"
)
const dateTimeLayout = "2006-01-02 15:04:00 -0700"
func TestMemoryStorage(t *testing.T) {
s := New()
dateParced1, _ := time.Parse(dateTimeLayout, "11.11.1111")
dateParced2, _ := time.Parse(dateTimeLayout, "22.11.22222")
t.Run("Empty storage", func(t *testing.T) {
require.Equal(t, 0, len(s.Events))
})
id, err := s.Create(event.Event{Title: "event1", Date: dateParced1})
t.Run("Create events", func(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 1, len(s.Events))
require.Equal(t, event.Event{Title: "event1", Date: dateParced1}, s.Events[id])
})
t.Run("Update event", func(t *testing.T) {
err := s.Update(id, event.Event{Title: "event1_modifyed", Date: dateParced2})
require.NoError(t, err)
require.Equal(t, 1, len(s.Events))
require.Equal(t, event.Event{Title: "event1_modifyed", Date: dateParced2}, s.Events[id])
})
t.Run("List event", func(t *testing.T) {
res, err := s.List()
require.NoError(t, err)
require.Equal(t, 1, len(res))
require.Equal(t, event.Event{Title: "event1_modifyed", Date: dateParced2}, res[id])
})
t.Run("Get event by ID", func(t *testing.T) {
res, ok := s.GetByID(id)
require.Equal(t, ok, true)
require.Equal(t, event.Event{Title: "event1_modifyed", Date: dateParced2}, res)
})
t.Run("Get event by fake ID", func(t *testing.T) {
res, ok := s.GetByID(53663)
require.Equal(t, ok, false)
require.Equal(t, event.Event{}, res)
})
t.Run("Delete event", func(t *testing.T) {
err := s.Delete(id)
require.NoError(t, err)
require.Equal(t, 0, len(s.Events))
})
}

View File

@ -1,56 +0,0 @@
package memorystorage
import (
"github.com/stretchr/testify/require"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event"
"testing"
)
func TestMemoryStorage(t *testing.T) {
s := New()
t.Run("Empty storage", func(t *testing.T) {
require.Equal(t,0, len(s.Events))
})
id,err:=s.Create(event.Event{ Title:"event1",Date:"11.11.1111" })
t.Run("Create events", func(t *testing.T) {
require.NoError(t,err)
require.Equal(t,1, len(s.Events))
require.Equal(t,event.Event{ Title:"event1",Date:"11.11.1111" }, s.Events[id])
})
t.Run("Update event", func(t *testing.T) {
err:=s.Update(id,event.Event{ Title:"event1_modifyed",Date:"22.11.22222" })
require.NoError(t,err)
require.Equal(t,1, len(s.Events))
require.Equal(t,event.Event{ Title:"event1_modifyed",Date:"22.11.22222" }, s.Events[id])
})
t.Run("List event", func(t *testing.T) {
res,err:=s.List()
require.NoError(t,err)
require.Equal(t,1, len(res))
require.Equal(t,event.Event{ Title:"event1_modifyed",Date:"22.11.22222" }, res[id])
})
t.Run("Get event by ID", func(t *testing.T) {
res,ok := s.GetByID(id)
require.Equal(t,ok,true)
require.Equal(t,event.Event{ Title:"event1_modifyed",Date:"22.11.22222" }, res)
})
t.Run("Get event by fake ID", func(t *testing.T) {
res,ok := s.GetByID(53663)
require.Equal(t,ok,false)
require.Equal(t,event.Event{}, res)
})
t.Run("Delete event", func(t *testing.T) {
err := s.Delete(id)
require.NoError(t,err)
require.Equal(t,0, len(s.Events))
})
}

View File

@ -1,11 +1,14 @@
package sqlstorage package sql
import ( import (
"database/sql" "database/sql"
"time"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event" "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/storage/event"
) )
const dateTimeLayout = "2006-01-02 15:04:00 -0700"
type Config struct { type Config struct {
User string User string
Pass string Pass string
@ -37,9 +40,15 @@ func (s *Storage) Close() error {
func (s *Storage) Create(event event.Event) (int64, error) { func (s *Storage) Create(event event.Event) (int64, error) {
res, err := s.db.Exec( res, err := s.db.Exec(
`INSERT INTO events (title, date) VALUES ($1, $2)`, `INSERT INTO events
(title, date, latency, note, userID, notifyTime) VALUES
($1, $2, $3, $4, $5, $6)`,
event.Title, event.Title,
event.Date, event.Date.Format(dateTimeLayout),
event.Latency,
event.Note,
event.UserID,
event.NotifyTime,
) )
if err != nil { if err != nil {
return -1, err return -1, err
@ -49,9 +58,15 @@ func (s *Storage) Create(event event.Event) (int64, error) {
func (s *Storage) Update(id int64, event event.Event) error { func (s *Storage) Update(id int64, event event.Event) error {
_, err := s.db.Exec( _, err := s.db.Exec(
`UPDATE events set title=$1, date=$2 where id=$3`, `UPDATE events set
title=$1, date=$2, latency=$3, note=$4, userID=$5, notifyTime=$6
where id=$7`,
event.Title, event.Title,
event.Date, event.Date.Format(dateTimeLayout),
event.Latency,
event.Note,
event.UserID,
event.NotifyTime,
id, id,
) )
return err return err
@ -68,32 +83,43 @@ func (s *Storage) Delete(id int64) error {
func (s *Storage) List() (map[int64]event.Event, error) { func (s *Storage) List() (map[int64]event.Event, error) {
res := make(map[int64]event.Event) res := make(map[int64]event.Event)
results, err := s.db.Query( results, err := s.db.Query(
`SELECT (id,title,date) from events ORDER BY id`) `SELECT (id,title,date,latency,note,userID,notifyTime) from events ORDER BY id`)
if err != nil || results.Err() != nil { if err != nil {
return res, err return map[int64]event.Event{}, err
} }
defer results.Close() defer results.Close()
for results.Next() { for results.Next() {
var tmp struct { var id int64
id int64 var evt event.Event
title string var dateRaw string
date string err = results.Scan(&id, &evt.Title, &dateRaw, &evt.Latency, &evt.Note, &evt.UserID, &evt.NotifyTime)
}
err = results.Scan(&tmp.id, &tmp.title, &tmp.date)
if err != nil { if err != nil {
return res, err return map[int64]event.Event{}, err
} }
res[tmp.id] = event.Event{Title: tmp.title, Date: tmp.date} evt.Date, err = time.Parse(dateTimeLayout, dateRaw)
if err != nil {
return map[int64]event.Event{}, err
}
res[id] = evt
}
if results.Err() != nil {
return map[int64]event.Event{}, results.Err()
} }
return res, nil return res, nil
} }
func (s *Storage) GetByID(id int64) (event.Event, bool) { func (s *Storage) GetByID(id int64) (event.Event, bool) {
var res event.Event var res event.Event
var dateRaw string
err := s.db.QueryRow( err := s.db.QueryRow(
`SELECT (title,date) from events where id=$1`, id).Scan(res.Title, res.Date) `SELECT (id,title,date,latency,note,userID,notifyTime) from events where id=$1`, id).Scan(res.Title, dateRaw, res.Latency, res.Note, res.UserID, res.NotifyTime)
if err != nil { if err != nil {
return res, false return res, false
} }
dateParced, err := time.Parse(dateTimeLayout, dateRaw)
if err != nil {
return res, false
}
res.Date = dateParced
return res, true return res, true
} }

View File

@ -3,7 +3,11 @@
CREATE TABLE events ( CREATE TABLE events (
id int(16) NOT NULL AUTO_INCREMENT, id int(16) NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL, title varchar(255) NOT NULL,
date varchar(255) NOT NULL, date datetime NOT NULL,
latency int(16) NOT NULL,
note text,
userID int(16),
notifyTime int(16)
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;;
-- +goose StatementEnd -- +goose StatementEnd