HW14 Completed

hw12_13_14_15_calendar
Andrey Ivanov 2020-11-23 15:22:13 +03:00 committed by tiburon
parent a0c0802838
commit 4976188993
47 changed files with 1347 additions and 306 deletions

View File

@ -1,22 +1,48 @@
cdir = $(shell pwd)
build:
build-all:
go build -o ./bin/calendar ./cmd/calendar/main.go
go build -o ./bin/scheduler ./cmd/scheduler/main.go
go build -o ./bin/sender ./cmd/sender/main.go
run:
go run ./cmd/calendar/main.go -config ./configs/config.toml
start: build-all rabbit-start calendar-start scheduler-start sender-start
stop: scheduler-stop sender-stop calendar-stop rabbit-stop
test:
go test -race ./internal/...
go test -race ./internal/... ./pkg/... --tags calendar
lint: install-lint-deps
golangci-lint run .cmd/... ./internal/...
golangci-lint run .cmd/... ./internal/... ./pkg/...
install-lint-deps:
(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
generate:
protoc -I ./grpcserver --go_out=plugins=grpc:./internal/grpcserver --grpc-gateway_out=logtostderr=true:./internal/grpcserver ./grpcserver/grpcserver.proto
protoc -I ./api/public --go_out=plugins=grpc:./pkg/api/public --grpc-gateway_out=logtostderr=true:./pkg/api/public ./api/public/grpcserver.proto
protoc -I ./api/private --go_out=plugins=grpc:./internal/api/private ./api/private/grpcserver.proto
rabbit-start:
sudo -S docker-compose -f ./cicd/docker-compose.yml up --build -d
rabbit-stop:
sudo -S docker-compose -f ./cicd/docker-compose.yml down
calendar-start:
nohup ./bin/calendar -config ./configs/calendar.conf > /dev/null 2>&1 &
calendar-stop:
kill -9 `pgrep calendar`
scheduler-start:
nohup ./bin/scheduler -config ./configs/scheduler.conf > /dev/null 2>&1 &
scheduler-stop:
kill -9 `pgrep scheduler`
sender-start:
nohup ./bin/sender -config ./configs/sender.conf > /dev/null 2>&1 &
sender-stop:
kill -9 `pgrep sender`
.PHONY: build run test lint

View File

@ -0,0 +1,29 @@
syntax = "proto3";
package private;
option go_package = "private";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
service grpc {
rpc GetNotifications(google.protobuf.Empty) returns (GetRsp) {}
rpc SetNotified(SetReq) returns (google.protobuf.Empty) {}
}
message GetRsp {
repeated Event Events = 1;
}
message SetReq {
int64 ID = 1;
}
message Event {
int64 ID = 1;
string Title = 2;
google.protobuf.Timestamp Date = 3;
int64 UserID = 4;
}

View File

@ -1,8 +1,8 @@
syntax = "proto3";
package grpcserver;
package public;
option go_package = "grpcserver";
option go_package = "public";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

View File

@ -0,0 +1,17 @@
version: '2.0'
services:
rabbitmq:
image: rabbitmq:3-management-alpine
hostname: "rabbitmq"
container_name: rabbitmq
environment:
RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG"
RABBITMQ_DEFAULT_USER: "rabbit"
RABBITMQ_DEFAULT_PASS: "rabbit"
RABBITMQ_DEFAULT_VHOST: "/"
ports:
- "5672:5672"
- "15672:15672"
expose:
- 5672
- 15672

View File

@ -4,6 +4,7 @@ import (
"context"
"flag"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/api/private"
"google.golang.org/grpc"
oslog "log"
"net"
@ -13,26 +14,27 @@ import (
"syscall"
_ "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/grpcserver"
"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/calendar"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/api/public"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/logger"
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage"
)
var configFile string
func init() {
flag.StringVar(&configFile, "config", "/etc/calendar/config.toml", "Path to configuration file")
flag.StringVar(&configFile, "config", "/etc/calendar.conf", "Path to configuration file")
flag.Parse()
}
func main() {
conf, err := config.NewConfig(configFile)
var conf config.Calendar
err := config.New(configFile, &conf)
if err != nil {
oslog.Fatal("не удалось открыть файл конфигурации:", err.Error())
}
log, err := logger.New(conf)
log, err := logger.New(logger.Config(conf.Logger))
if err != nil {
oslog.Fatal("не удалось запустить логер:", err.Error())
}
@ -46,9 +48,9 @@ func main() {
}
st := store.NewStore(storeConf)
calendar := app.New(log, st)
calendar := calendar.New(log, st)
serverGRPC := grpcserver.New(calendar)
serverGRPC := public.New(calendar)
go func() {
if err := serverGRPC.Start(conf); err != nil {
log.Errorf("failed to start grpc server: " + err.Error())
@ -56,6 +58,14 @@ func main() {
}
}()
serverAPI := private.New(calendar)
go func() {
if err := serverAPI.Start(private.Config(conf.API)); err != nil {
log.Errorf("failed to start API server: " + err.Error())
os.Exit(1)
}
}()
grpcDiler, err := grpc.Dial(net.JoinHostPort(conf.HTTP.Address, conf.HTTP.Port), grpc.WithInsecure())
if err != nil {
log.Errorf("can't dial grpc server: " + err.Error())
@ -65,7 +75,7 @@ func main() {
grpcGwRouter := runtime.NewServeMux()
if err = grpcserver.RegisterGrpcHandler(context.Background(), grpcGwRouter, grpcDiler); err != nil {
if err = public.RegisterGrpcHandler(context.Background(), grpcGwRouter, grpcDiler); err != nil {
log.Errorf("can't register handlers for grpc-gateway: " + err.Error())
os.Exit(1)
}
@ -81,7 +91,7 @@ func main() {
}()
signals := make(chan os.Signal, 1)
signal.Notify(signals,syscall.SIGINT)
signal.Notify(signals, syscall.SIGINT)
<-signals
signal.Stop(signals)
serverGRPC.Stop()

View File

@ -0,0 +1,42 @@
package main
import (
"context"
"flag"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/sheduler"
"log"
"os"
"os/signal"
"syscall"
_ "github.com/go-sql-driver/mysql"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
)
var configFile string
func init() {
flag.StringVar(&configFile, "config", "/etc/scheduler.conf", "Path to configuration file")
flag.Parse()
}
func main() {
var conf sheduler.Config
err := config.New(configFile, &conf)
if err != nil {
log.Fatal("не удалось открыть файл конфигурации:", err.Error())
}
app := sheduler.New(conf)
ctx, cancel := context.WithCancel(context.Background())
if err = app.Start(ctx); err != nil {
app.Logger.Errorf("failed to start scheduler: ", err.Error())
os.Exit(1)
}
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT)
<-signals
signal.Stop(signals)
app.Stop(cancel)
}

View File

@ -0,0 +1,42 @@
package main
import (
"context"
"flag"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/sender"
"log"
"os"
"os/signal"
"syscall"
_ "github.com/go-sql-driver/mysql"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
)
var configFile string
func init() {
flag.StringVar(&configFile, "config", "/etc/sender.conf", "Path to configuration file")
flag.Parse()
}
func main() {
var conf sender.Config
err := config.New(configFile, &conf)
if err != nil {
log.Fatal("не удалось открыть файл конфигурации:", err.Error())
}
app := sender.New(conf)
ctx, cancel := context.WithCancel(context.Background())
if err = app.Start(ctx); err != nil {
app.Logger.Errorf("failed to start sender: ", err.Error())
os.Exit(1)
}
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT)
<-signals
signal.Stop(signals)
app.Stop(cancel)
}

View File

@ -6,12 +6,16 @@ Port = "50051"
Address = "localhost"
Port = "50052"
[API]
Address = "localhost"
Port = "50053"
[Logger]
File = "./calendar.log"
Level = "INFO"
[Storage]
inMemory = false
inMemory = true
SQLHost = "localhost"
SQLPort = "5432"
SQLDbase = "calendar"

View File

@ -0,0 +1,16 @@
[Rabbitmq]
Address = "localhost"
Port = "5672"
Login = "rabbit"
Pass = "rabbit"
Exchange = "calendar"
Queue = "notifications"
Key = "events"
[Logger]
File = "./calendar.log"
Level = "INFO"
[API]
Address = "localhost"
Port = "50053"

View File

@ -0,0 +1,12 @@
[Rabbitmq]
Address = "localhost"
Port = "5672"
Login = "rabbit"
Pass = "rabbit"
Exchange = "calendar"
Queue = "notifications"
Key = "events"
[Logger]
File = "./calendar.log"
Level = "INFO"

View File

@ -1 +0,0 @@
version: "3"

View File

@ -5,18 +5,23 @@ go 1.14
require (
github.com/BurntSushi/toml v0.3.1
github.com/amitrai48/logger v0.0.0-20190214092904-448001c055ec
github.com/daixiang0/gci v0.2.4 // indirect
github.com/dmitryt/otus-golang-hw/hw12_13_14_15_calendar v0.0.0-20200916093948-5ca8860569b6
github.com/go-sql-driver/mysql v1.5.0
github.com/golang/protobuf v1.4.2
github.com/grpc-ecosystem/grpc-gateway v1.15.0
github.com/rs/zerolog v1.20.0
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/sirupsen/logrus v1.4.2 // indirect
github.com/streadway/amqp v1.0.0
github.com/stretchr/testify v1.6.1
go.uber.org/zap v1.15.0 // indirect
golang.org/x/net v0.0.0-20200625001655-4c5254603344
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
golang.org/x/text v0.3.3 // indirect
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305 // indirect
google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70
google.golang.org/grpc v1.32.0
google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)

View File

@ -1,49 +1,27 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/amitrai48/logger v0.0.0-20190214092904-448001c055ec h1:tDOPo9NAXCjvoK35HgZyzQSNLmb3chZqN2tnO273Bro=
github.com/amitrai48/logger v0.0.0-20190214092904-448001c055ec/go.mod h1:RZEHP3cxXvQlMuMjkpdh6qXA4b0CpjxnUBNxOpR0r30=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/daixiang0/gci v0.2.4/go.mod h1:+AV8KmHTGxxwp/pY84TLQfFKp2vuKXXJVzF3kD/hfR4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dmitryt/otus-golang-hw/hw12_13_14_15_calendar v0.0.0-20200916093948-5ca8860569b6 h1:kbX6KBmjfEYzBbEk2/bfAXgocxhzFQXH+5Tpr7gNg0k=
github.com/dmitryt/otus-golang-hw/hw12_13_14_15_calendar v0.0.0-20200916093948-5ca8860569b6/go.mod h1:f//zKg1isd70tsJVPWphzKLXd7pvW4Owmtobh4uhuCQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o=
github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@ -62,65 +40,37 @@ github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.1 h1:V59tBiPuMkySHwJkuq/OYkK0WnOLwCwD3UkTbEMr12U=
github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU=
github.com/grpc-ecosystem/grpc-gateway v1.15.0 h1:ntPNC9TD/6l2XDenJZe6T5lSMg95thpV9sGAqHX4WU8=
github.com/grpc-ecosystem/grpc-gateway v1.15.0/go.mod h1:vO11I9oWA+KsxmfFQPhLnnIb1VDE24M+pdxZFiuZcA8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ilyakaznacheev/cleanenv v1.2.5 h1:/SlcF9GaIvefWqFJzsccGG/NJdoaAwb7Mm7ImzhO3DM=
github.com/ilyakaznacheev/cleanenv v1.2.5/go.mod h1:/i3yhzwZ3s7hacNERGFwvlhwXMDcaqwIzmayEhbRplk=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pressly/goose v2.6.0+incompatible/go.mod h1:m+QHWCqxR3k8D9l7qfzuC/djtlfzxr34mozWDYEu1z8=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
@ -131,11 +81,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tiburon-777/HW_OTUS v0.0.0-20200927064133-fc19ac2e8966 h1:LjBeW5xHnZQP7ZlViMBSaKP+HJhLSkOdSj7K7lXdbzg=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@ -144,47 +91,34 @@ go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKY
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e h1:JgcxKXxCjrA2tyDP/aNU9K0Ck5Czfk6C7e2tMw7+bSI=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -197,43 +131,28 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305 h1:yaM5S0KcY0lIoZo7Fl+oi91b/DdlU2zuWpfHrpWbCS0=
golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
@ -243,10 +162,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
@ -256,8 +173,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0 h1:zWTV+LMdc3kaiJMSTOFz2UgSBgx8RNQoTGiZu3fR9S0=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@ -276,16 +191,14 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
@ -294,5 +207,3 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
olympos.io/encoding/edn v0.0.0-20200308123125-93e3b8dd0e24 h1:sreVOrDp0/ezb0CHKVek/l7YwpxPJqv+jT3izfSphA4=
olympos.io/encoding/edn v0.0.0-20200308123125-93e3b8dd0e24/go.mod h1:oVgVk4OWVDi43qWBEyGhXgYxt7+ED4iYNpTngSLX2Iw=

View File

@ -0,0 +1,22 @@
package private
import (
"github.com/golang/protobuf/ptypes"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage/event"
)
func (s Service) buildEventList(evtMap map[event.ID]event.Event) ([]*Event, error) {
events := make([]*Event, len(evtMap))
var err error
var i int
for k, v := range evtMap {
evt := Event{ID: int64(k), Title: v.Title, UserID: v.UserID}
evt.Date, err = ptypes.TimestampProto(v.Date)
if err != nil {
return nil, err
}
events[i] = &evt
i++
}
return events, err
}

View File

@ -0,0 +1,16 @@
package private
import (
"net"
"google.golang.org/grpc"
)
func NewClient(addr, port string) (GrpcClient, error) {
conn, err := grpc.Dial(net.JoinHostPort(addr, port), grpc.WithInsecure())
if err != nil {
return nil, err
}
client := NewGrpcClient(conn)
return client, nil
}

View File

@ -0,0 +1,314 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: grpcserver.proto
package private
import (
context "context"
fmt "fmt"
proto "github.com/golang/protobuf/proto"
empty "github.com/golang/protobuf/ptypes/empty"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type GetRsp struct {
Events []*Event `protobuf:"bytes,1,rep,name=Events,proto3" json:"Events,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetRsp) Reset() { *m = GetRsp{} }
func (m *GetRsp) String() string { return proto.CompactTextString(m) }
func (*GetRsp) ProtoMessage() {}
func (*GetRsp) Descriptor() ([]byte, []int) {
return fileDescriptor_afa6debe97205904, []int{0}
}
func (m *GetRsp) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetRsp.Unmarshal(m, b)
}
func (m *GetRsp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetRsp.Marshal(b, m, deterministic)
}
func (m *GetRsp) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetRsp.Merge(m, src)
}
func (m *GetRsp) XXX_Size() int {
return xxx_messageInfo_GetRsp.Size(m)
}
func (m *GetRsp) XXX_DiscardUnknown() {
xxx_messageInfo_GetRsp.DiscardUnknown(m)
}
var xxx_messageInfo_GetRsp proto.InternalMessageInfo
func (m *GetRsp) GetEvents() []*Event {
if m != nil {
return m.Events
}
return nil
}
type SetReq struct {
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SetReq) Reset() { *m = SetReq{} }
func (m *SetReq) String() string { return proto.CompactTextString(m) }
func (*SetReq) ProtoMessage() {}
func (*SetReq) Descriptor() ([]byte, []int) {
return fileDescriptor_afa6debe97205904, []int{1}
}
func (m *SetReq) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SetReq.Unmarshal(m, b)
}
func (m *SetReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SetReq.Marshal(b, m, deterministic)
}
func (m *SetReq) XXX_Merge(src proto.Message) {
xxx_messageInfo_SetReq.Merge(m, src)
}
func (m *SetReq) XXX_Size() int {
return xxx_messageInfo_SetReq.Size(m)
}
func (m *SetReq) XXX_DiscardUnknown() {
xxx_messageInfo_SetReq.DiscardUnknown(m)
}
var xxx_messageInfo_SetReq proto.InternalMessageInfo
func (m *SetReq) GetID() int64 {
if m != nil {
return m.ID
}
return 0
}
type Event struct {
ID int64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
Title string `protobuf:"bytes,2,opt,name=Title,proto3" json:"Title,omitempty"`
Date *timestamp.Timestamp `protobuf:"bytes,3,opt,name=Date,proto3" json:"Date,omitempty"`
UserID int64 `protobuf:"varint,4,opt,name=UserID,proto3" json:"UserID,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Event) Reset() { *m = Event{} }
func (m *Event) String() string { return proto.CompactTextString(m) }
func (*Event) ProtoMessage() {}
func (*Event) Descriptor() ([]byte, []int) {
return fileDescriptor_afa6debe97205904, []int{2}
}
func (m *Event) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Event.Unmarshal(m, b)
}
func (m *Event) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Event.Marshal(b, m, deterministic)
}
func (m *Event) XXX_Merge(src proto.Message) {
xxx_messageInfo_Event.Merge(m, src)
}
func (m *Event) XXX_Size() int {
return xxx_messageInfo_Event.Size(m)
}
func (m *Event) XXX_DiscardUnknown() {
xxx_messageInfo_Event.DiscardUnknown(m)
}
var xxx_messageInfo_Event proto.InternalMessageInfo
func (m *Event) GetID() int64 {
if m != nil {
return m.ID
}
return 0
}
func (m *Event) GetTitle() string {
if m != nil {
return m.Title
}
return ""
}
func (m *Event) GetDate() *timestamp.Timestamp {
if m != nil {
return m.Date
}
return nil
}
func (m *Event) GetUserID() int64 {
if m != nil {
return m.UserID
}
return 0
}
func init() {
proto.RegisterType((*GetRsp)(nil), "private.GetRsp")
proto.RegisterType((*SetReq)(nil), "private.SetReq")
proto.RegisterType((*Event)(nil), "private.Event")
}
func init() { proto.RegisterFile("grpcserver.proto", fileDescriptor_afa6debe97205904) }
var fileDescriptor_afa6debe97205904 = []byte{
// 286 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x4f, 0x6b, 0x32, 0x31,
0x10, 0x87, 0x5d, 0xff, 0xec, 0x8b, 0x23, 0xf8, 0x4a, 0x28, 0x12, 0xb6, 0x87, 0x2e, 0x7b, 0x28,
0x7b, 0x8a, 0xc5, 0x5e, 0x7a, 0xe9, 0xa5, 0xac, 0x88, 0x97, 0x1e, 0xa2, 0xbd, 0xf4, 0xb6, 0xda,
0x51, 0x02, 0x6a, 0xd2, 0x64, 0x5c, 0xe8, 0xa9, 0x5f, 0xbd, 0x98, 0xec, 0xb6, 0x60, 0xe9, 0x71,
0xe6, 0xf7, 0x64, 0x32, 0x4f, 0x02, 0xa3, 0x9d, 0x35, 0x1b, 0x87, 0xb6, 0x42, 0x2b, 0x8c, 0xd5,
0xa4, 0xd9, 0x3f, 0x63, 0x55, 0x55, 0x12, 0x26, 0x37, 0x3b, 0xad, 0x77, 0x7b, 0x9c, 0xf8, 0xf6,
0xfa, 0xb4, 0x9d, 0x90, 0x3a, 0xa0, 0xa3, 0xf2, 0x60, 0x02, 0x99, 0x5c, 0x5f, 0x02, 0x78, 0x30,
0xf4, 0x11, 0xc2, 0xec, 0x0e, 0xe2, 0x39, 0x92, 0x74, 0x86, 0xdd, 0x42, 0x3c, 0xab, 0xf0, 0x48,
0x8e, 0x47, 0x69, 0x27, 0x1f, 0x4c, 0x87, 0xa2, 0xbe, 0x41, 0xf8, 0xb6, 0xac, 0xd3, 0x8c, 0x43,
0xbc, 0x44, 0x92, 0xf8, 0xce, 0x86, 0xd0, 0x5e, 0x14, 0x3c, 0x4a, 0xa3, 0xbc, 0x23, 0xdb, 0x8b,
0x22, 0x3b, 0x41, 0xcf, 0x33, 0x97, 0x01, 0xbb, 0x82, 0xde, 0x4a, 0xd1, 0x1e, 0x79, 0x3b, 0x8d,
0xf2, 0xbe, 0x0c, 0x05, 0x13, 0xd0, 0x2d, 0x4a, 0x42, 0xde, 0x49, 0xa3, 0x7c, 0x30, 0x4d, 0x44,
0x58, 0x53, 0x34, 0x6b, 0x8a, 0x55, 0xe3, 0x21, 0x3d, 0xc7, 0xc6, 0x10, 0xbf, 0x38, 0xb4, 0x8b,
0x82, 0x77, 0xfd, 0xe4, 0xba, 0x9a, 0x7e, 0x42, 0xf7, 0xfc, 0x3a, 0xec, 0x11, 0x46, 0x73, 0xa4,
0x67, 0x4d, 0x6a, 0xab, 0x36, 0x25, 0x29, 0x7d, 0x74, 0x6c, 0xfc, 0x6b, 0xea, 0xec, 0x2c, 0x9f,
0xfc, 0xff, 0x96, 0x0b, 0xf6, 0x59, 0x8b, 0x3d, 0xc0, 0x60, 0xd9, 0x1c, 0xc7, 0x37, 0xf6, 0x43,
0x04, 0xdb, 0xe4, 0x8f, 0x51, 0x59, 0xeb, 0xa9, 0xff, 0xda, 0x7c, 0xc6, 0x3a, 0xf6, 0xe1, 0xfd,
0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0x5f, 0x05, 0xc6, 0xb0, 0x01, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// GrpcClient is the client API for Grpc service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type GrpcClient interface {
GetNotifications(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*GetRsp, error)
SetNotified(ctx context.Context, in *SetReq, opts ...grpc.CallOption) (*empty.Empty, error)
}
type grpcClient struct {
cc *grpc.ClientConn
}
func NewGrpcClient(cc *grpc.ClientConn) GrpcClient {
return &grpcClient{cc}
}
func (c *grpcClient) GetNotifications(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*GetRsp, error) {
out := new(GetRsp)
err := c.cc.Invoke(ctx, "/private.grpc/GetNotifications", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *grpcClient) SetNotified(ctx context.Context, in *SetReq, opts ...grpc.CallOption) (*empty.Empty, error) {
out := new(empty.Empty)
err := c.cc.Invoke(ctx, "/private.grpc/SetNotified", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// GrpcServer is the server API for Grpc service.
type GrpcServer interface {
GetNotifications(context.Context, *empty.Empty) (*GetRsp, error)
SetNotified(context.Context, *SetReq) (*empty.Empty, error)
}
// UnimplementedGrpcServer can be embedded to have forward compatible implementations.
type UnimplementedGrpcServer struct {
}
func (*UnimplementedGrpcServer) GetNotifications(ctx context.Context, req *empty.Empty) (*GetRsp, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetNotifications not implemented")
}
func (*UnimplementedGrpcServer) SetNotified(ctx context.Context, req *SetReq) (*empty.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetNotified not implemented")
}
func RegisterGrpcServer(s *grpc.Server, srv GrpcServer) {
s.RegisterService(&_Grpc_serviceDesc, srv)
}
func _Grpc_GetNotifications_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(empty.Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GrpcServer).GetNotifications(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/private.grpc/GetNotifications",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).GetNotifications(ctx, req.(*empty.Empty))
}
return interceptor(ctx, in, info, handler)
}
func _Grpc_SetNotified_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SetReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GrpcServer).SetNotified(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/private.grpc/SetNotified",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).SetNotified(ctx, req.(*SetReq))
}
return interceptor(ctx, in, info, handler)
}
var _Grpc_serviceDesc = grpc.ServiceDesc{
ServiceName: "private.grpc",
HandlerType: (*GrpcServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetNotifications",
Handler: _Grpc_GetNotifications_Handler,
},
{
MethodName: "SetNotified",
Handler: _Grpc_SetNotified_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "grpcserver.proto",
}

View File

@ -0,0 +1,31 @@
package private
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/calendar"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage/event"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type Service struct {
App calendar.App
}
func (s Service) GetNotifications(ctx context.Context, e *empty.Empty) (*GetRsp, error) {
tmp, err := s.App.Storage.GetNotifications()
if err != nil {
return nil, status.Errorf(codes.Internal, "storage error: can't get list of events")
}
l, err := s.buildEventList(tmp)
if err != nil {
return nil, status.Errorf(codes.Internal, "inconvertible")
}
return &GetRsp{Events: l}, nil
}
func (s Service) SetNotified(ctx context.Context, r *SetReq) (*empty.Empty, error) {
return nil, s.App.Storage.SetNotified(event.ID(r.ID))
}

View File

@ -0,0 +1,84 @@
package private
import (
"github.com/stretchr/testify/suite"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/calendar"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/logger"
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage/event"
oslog "log"
"testing"
"time"
)
var conf = config.Calendar{
HTTP: config.Server{Address: "localhost", Port: "50511"},
GRPC: config.Server{Address: "localhost", Port: "50512"},
API: config.Server{Address: "localhost", Port: "50513"},
Logger: config.Logger{File: "calendar.log", Level: "INFO", MuteStdout: false},
Storage: config.Storage{InMemory: true, SQLHost: "", SQLPort: "", SQLDbase: "", SQLUser: "", SQLPass: ""}}
var storeConf = store.Config(conf.Storage)
var testEvt = event.Event{Title: "Test event 1", Date: time.Now(), Latency: time.Hour * 24, Note: "First gen", UserID: 1111, NotifyTime: 0, Notified: false}
func TestCalendarSuite(t *testing.T) {
suite.Run(t, new(TestSuite))
}
type TestSuite struct {
suite.Suite
srv Service
}
func (suite *TestSuite) SetupTest() {
log, err := logger.New(logger.Config(conf.Logger))
if err != nil {
oslog.Fatal("can't init logger")
}
suite.srv = Service{App: *calendar.New(log, store.NewStore(storeConf))}
}
func (s *TestSuite) TestGetNotifications() {
controlEvent := testEvt
s.createEvent(controlEvent)
returnedEvent := s.getNotifications()
s.Equal(controlEvent.Title, returnedEvent.Title)
s.Equal(controlEvent.UserID, returnedEvent.UserID)
}
func (s *TestSuite) TestSetNotified() {
controlEvent := testEvt
id := s.createEvent(controlEvent)
s.setNotified(id)
returnedEvent := s.getEventByID(id)
s.Equal(true, returnedEvent.Notified)
}
func (s *TestSuite) createEvent(ev event.Event) event.ID {
createdEvent, err := s.srv.App.Storage.Create(ev)
s.NoError(err, "can,t create event")
s.NotEqual(createdEvent, 0, `message ID may not be a "0"`)
return createdEvent
}
func (s *TestSuite) getNotifications() Event {
evs, err := s.srv.GetNotifications(nil, nil)
s.NoError(err, "can't get events")
s.Equal(1, len(evs.Events), "length of slice in responce must be a \"1\"")
return *evs.Events[0]
}
func (s *TestSuite) setNotified(id event.ID) {
_, err := s.srv.SetNotified(nil, &SetReq{ID: int64(id)})
s.NoError(err, "can't mark event as notified")
}
func (s *TestSuite) getEventByID(id event.ID) event.Event {
r, ok := s.srv.App.Storage.GetByID(id)
s.Equal(true, ok, "can't get event by id")
return r
}

View File

@ -0,0 +1,36 @@
package private
import (
"net"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/calendar"
googrpc "google.golang.org/grpc"
)
type Server struct {
s *googrpc.Server
app calendar.App
}
type Config struct {
Address string
Port string
}
func New(app *calendar.App) Server {
return Server{s: googrpc.NewServer(), app: *app}
}
func (s *Server) Start(conf Config) error {
s.app.Logger.Infof("GRPC server starting")
listnGrpc, err := net.Listen("tcp", net.JoinHostPort(conf.Address, conf.Port))
RegisterGrpcServer(s.s, &Service{})
if err != nil {
return err
}
return s.s.Serve(listnGrpc)
}
func (s *Server) Stop() {
s.s.GracefulStop()
}

View File

@ -1,13 +1,12 @@
package app
package calendar
import (
"context"
"net/http"
"time"
"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"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/logger"
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage"
)
type Interface interface {
@ -25,15 +24,6 @@ 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!"))

View File

@ -1,51 +0,0 @@
package config
import (
"io/ioutil"
"os"
"github.com/BurntSushi/toml"
)
type Config struct {
GRPC Server
HTTP Server
Logger Logger
Storage Storage
}
type Server struct {
Address string
Port string
}
type Logger struct {
File string
Level string
MuteStdout bool
}
type Storage struct {
InMemory bool
SQLHost string
SQLPort string
SQLDbase string
SQLUser string
SQLPass string
}
// Confita может быти и хороша, но она не возвращает ошибки, если не может распарсить файл в структуру. Мне не нравится такая "молчаливость".
func NewConfig(configFile string) (Config, error) {
f, err := os.Open(configFile)
if err != nil {
return Config{}, err
}
defer f.Close()
s, err := ioutil.ReadAll(f)
if err != nil {
return Config{}, err
}
var config Config
_, err = toml.Decode(string(s), &config)
return config, err
}

View File

@ -0,0 +1,65 @@
package sender
import (
"context"
"encoding/json"
oslog "log"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/api/private"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/logger"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/rabbit"
)
type Sender struct {
Logger logger.Interface
Rabbit *rabbit.Rabbit
Queue string
}
type Config struct {
Rabbitmq config.Rabbit
Logger config.Logger
}
func New(conf Config) Sender {
log, err := logger.New(logger.Config(conf.Logger))
if err != nil {
oslog.Fatal("не удалось запустить логер:", err.Error())
}
rb, err := rabbit.Attach(rabbit.Config(conf.Rabbitmq))
if err != nil {
log.Fatalf("failed to connect to RabbitMQ:", err.Error())
}
return Sender{Logger: log, Rabbit: rb, Queue: conf.Rabbitmq.Queue}
}
func (s *Sender) Start(ctx context.Context) error {
msg, err := s.Rabbit.Consume(ctx, s.Queue)
if err != nil {
return err
}
go func() {
for {
select {
case m := <-msg:
var data []private.Event
err := json.Unmarshal(m.Data, &data)
if err != nil {
s.Logger.Errorf("can`t unmarshal data", err)
}
for _, v := range data {
s.Logger.Infof("User %s notified about event %s", v.UserID, v.ID)
}
case <-ctx.Done():
return
}
}
}()
return nil
}
func (s *Sender) Stop(cancel context.CancelFunc) {
cancel()
}

View File

@ -0,0 +1,58 @@
package sheduler
import (
"context"
oslog "log"
"time"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/logger"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/rabbit"
)
type Scheduler struct {
CalendarAPI config.Server
Logger logger.Interface
Rabbit *rabbit.Rabbit
}
type Config struct {
CalendarAPI config.Server
Rabbitmq config.Rabbit
Storage config.Storage
Logger config.Logger
}
func New(conf Config) Scheduler {
log, err := logger.New(logger.Config(conf.Logger))
if err != nil {
oslog.Fatal("не удалось запустить логер:", err.Error())
}
rb, err := rabbit.New(rabbit.Config(conf.Rabbitmq))
if err != nil {
log.Fatalf("failed to connect to RabbitMQ:", err.Error())
}
return Scheduler{CalendarAPI: conf.CalendarAPI, Logger: log, Rabbit: rb}
}
func (s *Scheduler) Start(ctx context.Context) error {
fetcher := riseOnTick(ctx, s.Logger, func() interface{} { return worker(ctx, s.CalendarAPI, s.Rabbit) }, 1*time.Minute)
go func() {
for {
select {
case err := <-fetcher:
s.Logger.Infof("fetcher closed")
if err != nil {
s.Logger.Errorf("...with error:", err)
}
case <-ctx.Done():
return
}
}
}()
return nil
}
func (s *Scheduler) Stop(cancel context.CancelFunc) {
cancel()
}

View File

@ -0,0 +1,60 @@
package sheduler
import (
"context"
"encoding/json"
"time"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/api/private"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/logger"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/rabbit"
)
func riseOnTick(ctx context.Context, log logger.Interface, fn func() interface{}, interval time.Duration) <-chan interface{} {
valueStream := make(chan interface{})
go func() {
t := time.NewTicker(interval)
defer func() {
t.Stop()
close(valueStream)
}()
for {
select {
case <-ctx.Done():
return
case <-t.C:
select {
case <-ctx.Done():
return
default:
log.Infof("scheduler come to rabbit")
valueStream <- fn()
}
}
}
}()
return valueStream
}
func worker(ctx context.Context, calendarAPI config.Server, rb *rabbit.Rabbit) error {
cli, err := private.NewClient(calendarAPI.Address, calendarAPI.Port)
if err != nil {
return err
}
resp, err := cli.GetNotifications(ctx, nil)
if err != nil {
return err
}
for event := range resp.Events {
b, err := json.Marshal(event)
if err != nil {
return err
}
err = rb.Publish(string(b))
if err != nil {
return err
}
}
return nil
}

View File

@ -7,7 +7,8 @@ CREATE TABLE events (
latency int(16) NOT NULL,
note text,
userID int(16),
notifyTime int(16)
notifyTime int(16),
notified bool
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;;
-- +goose StatementEnd

View File

@ -1,10 +1,10 @@
package grpcserver
package public
import (
"time"
"github.com/golang/protobuf/ptypes"
"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/pkg/storage/event"
)
func (s Service) buildStorageEvent(pbe *CreateReq) (res event.Event, err error) {

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: grpcserver.proto
package grpcserver
package public
import (
context "context"
@ -466,7 +466,7 @@ func (m *GetByIDResp) GetEvents() []*Event {
type GetByDateReq struct {
Date *timestamp.Timestamp `protobuf:"bytes,1,opt,name=Date,proto3" json:"Date,omitempty"`
Range QueryRange `protobuf:"varint,2,opt,name=Range,proto3,enum=grpcserver.QueryRange" json:"Range,omitempty"`
Range QueryRange `protobuf:"varint,2,opt,name=Range,proto3,enum=public.QueryRange" json:"Range,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -551,61 +551,62 @@ func (m *GetByDateResp) GetEvents() []*Event {
}
func init() {
proto.RegisterEnum("grpcserver.QueryRange", QueryRange_name, QueryRange_value)
proto.RegisterType((*Event)(nil), "grpcserver.Event")
proto.RegisterType((*CreateReq)(nil), "grpcserver.CreateReq")
proto.RegisterType((*CreateRsp)(nil), "grpcserver.CreateRsp")
proto.RegisterType((*UpdateReq)(nil), "grpcserver.UpdateReq")
proto.RegisterType((*DeleteReq)(nil), "grpcserver.DeleteReq")
proto.RegisterType((*ListResp)(nil), "grpcserver.ListResp")
proto.RegisterType((*GetByIDReq)(nil), "grpcserver.GetByIDReq")
proto.RegisterType((*GetByIDResp)(nil), "grpcserver.GetByIDResp")
proto.RegisterType((*GetByDateReq)(nil), "grpcserver.GetByDateReq")
proto.RegisterType((*GetByDateResp)(nil), "grpcserver.GetByDateResp")
proto.RegisterEnum("public.QueryRange", QueryRange_name, QueryRange_value)
proto.RegisterType((*Event)(nil), "public.Event")
proto.RegisterType((*CreateReq)(nil), "public.CreateReq")
proto.RegisterType((*CreateRsp)(nil), "public.CreateRsp")
proto.RegisterType((*UpdateReq)(nil), "public.UpdateReq")
proto.RegisterType((*DeleteReq)(nil), "public.DeleteReq")
proto.RegisterType((*ListResp)(nil), "public.ListResp")
proto.RegisterType((*GetByIDReq)(nil), "public.GetByIDReq")
proto.RegisterType((*GetByIDResp)(nil), "public.GetByIDResp")
proto.RegisterType((*GetByDateReq)(nil), "public.GetByDateReq")
proto.RegisterType((*GetByDateResp)(nil), "public.GetByDateResp")
}
func init() { proto.RegisterFile("grpcserver.proto", fileDescriptor_afa6debe97205904) }
var fileDescriptor_afa6debe97205904 = []byte{
// 608 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x95, 0x4f, 0x6f, 0xd3, 0x4c,
0x10, 0xc6, 0x5f, 0x27, 0x8e, 0x53, 0x4f, 0xf3, 0x96, 0x74, 0x14, 0x52, 0xd7, 0xad, 0x4a, 0xb4,
0x17, 0x42, 0x84, 0x6c, 0x29, 0x15, 0x12, 0xf4, 0x46, 0x71, 0x04, 0x81, 0x36, 0x14, 0x2b, 0x15,
0x82, 0x13, 0x6e, 0xbb, 0x8d, 0x2c, 0x25, 0xb6, 0xb1, 0x37, 0x95, 0xa2, 0x2a, 0x17, 0xbe, 0x02,
0x1f, 0x8d, 0xaf, 0xc0, 0x15, 0xee, 0xdc, 0x90, 0xd7, 0x6b, 0xc7, 0xf9, 0x27, 0xe8, 0x99, 0x5b,
0x76, 0x9f, 0x99, 0xdf, 0xcc, 0xec, 0x3c, 0x8a, 0xa1, 0x3a, 0x08, 0x83, 0xcb, 0x88, 0x86, 0x37,
0x34, 0x34, 0x82, 0xd0, 0x67, 0x3e, 0xc2, 0xec, 0x46, 0x7f, 0x30, 0xf0, 0xfd, 0xc1, 0x90, 0x9a,
0x5c, 0xb9, 0x18, 0x5f, 0x9b, 0xcc, 0x1d, 0xd1, 0x88, 0x39, 0xa3, 0x20, 0x09, 0xd6, 0x0f, 0x16,
0x03, 0xae, 0xc6, 0xa1, 0xc3, 0x5c, 0xdf, 0x13, 0xfa, 0xde, 0xa2, 0x4e, 0x47, 0x01, 0x9b, 0x08,
0x71, 0x5f, 0x88, 0x4e, 0xe0, 0x9a, 0x8e, 0xe7, 0xf9, 0x8c, 0x67, 0x46, 0x89, 0x4a, 0x7e, 0x49,
0x50, 0xea, 0xdc, 0x50, 0x8f, 0xe1, 0x16, 0x14, 0xba, 0x96, 0x26, 0x35, 0xa4, 0x66, 0xd1, 0x2e,
0x74, 0x2d, 0xac, 0x41, 0xa9, 0xef, 0xb2, 0x21, 0xd5, 0x0a, 0x0d, 0xa9, 0xa9, 0xda, 0xc9, 0x01,
0x0d, 0x90, 0x2d, 0x87, 0x51, 0xad, 0xd8, 0x90, 0x9a, 0x9b, 0x6d, 0xdd, 0x48, 0xe0, 0x46, 0x5a,
0xd9, 0xe8, 0xa7, 0xad, 0xdb, 0x3c, 0x0e, 0x0f, 0xa1, 0x7c, 0xe2, 0x30, 0xea, 0x5d, 0x4e, 0x34,
0x99, 0xa7, 0xec, 0x2e, 0xa5, 0x58, 0x62, 0x18, 0x3b, 0x8d, 0x44, 0x04, 0xb9, 0xe7, 0x33, 0xaa,
0x95, 0x78, 0x65, 0xfe, 0x1b, 0xeb, 0xa0, 0x9c, 0x47, 0x34, 0xec, 0x5a, 0x9a, 0xc2, 0x5b, 0x14,
0x27, 0x7c, 0x06, 0xd0, 0xf3, 0x99, 0x7b, 0x3d, 0x89, 0x2b, 0x6b, 0xe5, 0x3f, 0xd5, 0xc8, 0x05,
0x93, 0x1f, 0x12, 0xa8, 0x2f, 0x42, 0xea, 0x30, 0x6a, 0xd3, 0xcf, 0xff, 0xc0, 0xbc, 0x7b, 0xd9,
0xb8, 0x51, 0xb0, 0xb8, 0x6e, 0x62, 0x81, 0x7a, 0x1e, 0x5c, 0x89, 0xb7, 0x58, 0xf4, 0xc2, 0x43,
0x61, 0x12, 0xfe, 0x36, 0x9b, 0xed, 0x6d, 0x23, 0xe7, 0x67, 0x2e, 0xd8, 0x89, 0x1e, 0x97, 0xb0,
0xe8, 0x90, 0xae, 0xa4, 0x90, 0x27, 0xb0, 0x71, 0xe2, 0x46, 0xcc, 0xa6, 0x51, 0x80, 0x8f, 0x40,
0xe1, 0x19, 0x91, 0x26, 0x35, 0x8a, 0xab, 0x91, 0x22, 0x80, 0xec, 0x03, 0xbc, 0xa4, 0xec, 0x78,
0xd2, 0xb5, 0x56, 0x41, 0x9f, 0xc2, 0x66, 0xa6, 0xde, 0x8d, 0x3b, 0x84, 0x0a, 0xcf, 0xb4, 0xc4,
0xd0, 0xe9, 0xaa, 0xa5, 0xbf, 0x5c, 0xf5, 0x63, 0x28, 0xd9, 0x8e, 0x37, 0x48, 0x0c, 0xb3, 0xd5,
0xae, 0xe7, 0x2b, 0xbd, 0x1b, 0xd3, 0x70, 0xc2, 0x55, 0x3b, 0x09, 0x22, 0x47, 0xf0, 0x7f, 0xae,
0xda, 0x9d, 0x3a, 0x6d, 0xb5, 0x00, 0x66, 0x40, 0x2c, 0x43, 0xd1, 0x7a, 0xfe, 0xa1, 0xfa, 0x1f,
0x6e, 0x80, 0xfc, 0xbe, 0xd3, 0x79, 0x53, 0x95, 0x50, 0x85, 0xd2, 0xe9, 0xdb, 0x5e, 0xff, 0x55,
0xb5, 0xd0, 0xfe, 0x59, 0x04, 0x39, 0x06, 0xe1, 0x6b, 0x50, 0x92, 0x6d, 0xe3, 0xfd, 0x3c, 0x39,
0x33, 0xbc, 0xbe, 0xea, 0x3a, 0x0a, 0x08, 0x7e, 0xf9, 0xf6, 0xfd, 0x6b, 0xa1, 0x42, 0xca, 0x26,
0xe5, 0xd5, 0x8f, 0xa4, 0x16, 0x9e, 0x81, 0x92, 0x98, 0x63, 0x9e, 0x95, 0x19, 0x46, 0xaf, 0x2f,
0xbd, 0x56, 0x27, 0xfe, 0x0b, 0x22, 0x3b, 0x1c, 0xb6, 0xad, 0x57, 0x04, 0xcc, 0xbc, 0xed, 0x5a,
0xd3, 0x98, 0x78, 0x0a, 0x4a, 0x62, 0x94, 0x79, 0x62, 0x66, 0x9e, 0xb5, 0xc4, 0x1a, 0x27, 0x6e,
0xb5, 0xe6, 0x88, 0xd8, 0x01, 0x39, 0xb6, 0x16, 0xae, 0xc9, 0xd2, 0x6b, 0xf9, 0x22, 0xa9, 0x09,
0xc9, 0x3d, 0xce, 0x52, 0x31, 0x1d, 0x15, 0xcf, 0xa0, 0x2c, 0xcc, 0x84, 0x73, 0xeb, 0x9c, 0xf9,
0x4f, 0xdf, 0x59, 0x79, 0x1f, 0x05, 0x69, 0x63, 0x38, 0xdf, 0xd8, 0x27, 0x50, 0xb3, 0xb5, 0xa3,
0xb6, 0x94, 0x2b, 0xbc, 0xa7, 0xef, 0xae, 0x51, 0xa2, 0x80, 0x1c, 0x70, 0xae, 0x46, 0xea, 0x19,
0x97, 0xdb, 0x60, 0x6a, 0xde, 0xc6, 0x21, 0xd3, 0xe3, 0xca, 0xc7, 0xdc, 0xb7, 0xe4, 0x42, 0xe1,
0x83, 0x1f, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xc6, 0xe4, 0xd7, 0xf2, 0x72, 0x06, 0x00, 0x00,
// 613 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x95, 0xcb, 0x6e, 0xd3, 0x5c,
0x10, 0xc7, 0x3f, 0x27, 0x8e, 0x53, 0x4f, 0x2f, 0x5f, 0x3a, 0x94, 0x62, 0xdc, 0xaa, 0x44, 0x07,
0x21, 0x45, 0x59, 0xd8, 0x22, 0x45, 0x48, 0xb0, 0xa2, 0xc5, 0x11, 0xb5, 0x28, 0x45, 0x58, 0xa9,
0xb8, 0xec, 0x9c, 0xf4, 0x34, 0x58, 0x4a, 0xec, 0x83, 0x7d, 0x52, 0x29, 0xaa, 0xb2, 0xe1, 0x15,
0x78, 0x2b, 0xb6, 0xbc, 0x02, 0x5b, 0x1e, 0x80, 0x1d, 0xf2, 0xf1, 0xb1, 0xd3, 0x5c, 0x2a, 0xb2,
0x67, 0x17, 0xcf, 0x7f, 0xe6, 0x37, 0x33, 0x9e, 0xbf, 0x1c, 0xa8, 0xf5, 0x63, 0xd6, 0x4b, 0x68,
0x7c, 0x45, 0x63, 0x8b, 0xc5, 0x11, 0x8f, 0x50, 0x63, 0xa3, 0xee, 0x20, 0xe8, 0x99, 0x0f, 0xfa,
0x51, 0xd4, 0x1f, 0x50, 0x5b, 0x44, 0xbb, 0xa3, 0x4b, 0x9b, 0x07, 0x43, 0x9a, 0x70, 0x7f, 0xc8,
0xb2, 0x44, 0xf3, 0x60, 0x3e, 0xe1, 0x62, 0x14, 0xfb, 0x3c, 0x88, 0x42, 0xa9, 0xef, 0xcd, 0xeb,
0x74, 0xc8, 0xf8, 0x58, 0x8a, 0xfb, 0x52, 0xf4, 0x59, 0x60, 0xfb, 0x61, 0x18, 0x71, 0x51, 0x99,
0x64, 0x2a, 0xf9, 0xad, 0x40, 0xa5, 0x7d, 0x45, 0x43, 0x8e, 0x5b, 0x50, 0x72, 0x1d, 0x43, 0xa9,
0x2b, 0x8d, 0xb2, 0x57, 0x72, 0x1d, 0xdc, 0x81, 0x4a, 0x27, 0xe0, 0x03, 0x6a, 0x94, 0xea, 0x4a,
0x43, 0xf7, 0xb2, 0x07, 0xb4, 0x40, 0x75, 0x7c, 0x4e, 0x8d, 0x72, 0x5d, 0x69, 0xac, 0xb7, 0x4c,
0x2b, 0x83, 0x5b, 0x79, 0x67, 0xab, 0x93, 0x8f, 0xee, 0x89, 0x3c, 0x3c, 0x84, 0xea, 0xa9, 0xcf,
0x69, 0xd8, 0x1b, 0x1b, 0xaa, 0x28, 0xb9, 0xbf, 0x50, 0xe2, 0xc8, 0x65, 0xbc, 0x3c, 0x13, 0x11,
0xd4, 0xb3, 0x88, 0x53, 0xa3, 0x22, 0x3a, 0x8b, 0xdf, 0xb8, 0x0b, 0xda, 0x79, 0x42, 0x63, 0xd7,
0x31, 0x34, 0x31, 0xa2, 0x7c, 0xc2, 0x67, 0x00, 0x67, 0x11, 0x0f, 0x2e, 0xc7, 0x69, 0x67, 0xa3,
0xfa, 0xb7, 0x1e, 0x37, 0x92, 0xc9, 0x2f, 0x05, 0xf4, 0x97, 0x31, 0xf5, 0x39, 0xf5, 0xe8, 0x97,
0x7f, 0x60, 0xdf, 0xbd, 0x62, 0xdd, 0x84, 0xcd, 0x9f, 0x9b, 0xbc, 0x00, 0xfd, 0x9c, 0x5d, 0xc8,
0x77, 0x31, 0xef, 0x85, 0x87, 0xd2, 0x24, 0xe2, 0xdd, 0xac, 0xb7, 0x36, 0xad, 0xcc, 0xb9, 0x96,
0x08, 0x7a, 0x99, 0x96, 0xe2, 0x1d, 0x3a, 0xa0, 0x4b, 0x09, 0xe4, 0x31, 0xac, 0x9d, 0x06, 0x09,
0xf7, 0x68, 0xc2, 0xf0, 0x11, 0x68, 0xa2, 0x22, 0x31, 0x94, 0x7a, 0x79, 0x11, 0x27, 0x45, 0xb2,
0x0f, 0xf0, 0x8a, 0xf2, 0xe3, 0xb1, 0xeb, 0x2c, 0x03, 0x3e, 0x81, 0xf5, 0x42, 0x5d, 0x9d, 0xf9,
0x19, 0x36, 0x44, 0x95, 0x23, 0x17, 0xcd, 0xcf, 0xab, 0xac, 0x78, 0xde, 0x06, 0x54, 0x3c, 0x3f,
0xec, 0x67, 0x26, 0xd9, 0x6a, 0x61, 0xde, 0xe5, 0xdd, 0x88, 0xc6, 0x63, 0xa1, 0x78, 0x59, 0x02,
0x79, 0x0a, 0x9b, 0x37, 0x3a, 0xad, 0x3c, 0x61, 0xb3, 0x09, 0x30, 0x85, 0x61, 0x15, 0xca, 0xce,
0xd1, 0xc7, 0xda, 0x7f, 0xb8, 0x06, 0xea, 0xfb, 0x76, 0xfb, 0x75, 0x4d, 0x41, 0x1d, 0x2a, 0x6f,
0xde, 0x9e, 0x75, 0x4e, 0x6a, 0xa5, 0xd6, 0xf7, 0x32, 0xa8, 0xe9, 0x57, 0x05, 0x8f, 0x41, 0xcb,
0x2e, 0x8b, 0xdb, 0x39, 0xb5, 0x30, 0xb6, 0x39, 0x1f, 0x4a, 0x18, 0xc1, 0xaf, 0x3f, 0x7e, 0x7e,
0x2b, 0x6d, 0x90, 0xaa, 0x4d, 0x45, 0xd7, 0xe7, 0x4a, 0x13, 0x4f, 0x41, 0xcb, 0x0c, 0x30, 0x65,
0x14, 0x86, 0x30, 0x77, 0x17, 0xde, 0x4c, 0x3b, 0xfd, 0xc4, 0x90, 0x7b, 0x02, 0xb4, 0x6d, 0x6e,
0x48, 0x90, 0x7d, 0xed, 0x3a, 0x93, 0x94, 0xe6, 0x82, 0x96, 0x99, 0x61, 0x4a, 0x2b, 0xcc, 0x71,
0x2b, 0x6d, 0x47, 0xd0, 0xb6, 0x9a, 0x33, 0x34, 0x3c, 0x02, 0x35, 0xb5, 0x0e, 0xde, 0x52, 0x65,
0xd6, 0xf2, 0x06, 0xb9, 0xc1, 0xc8, 0xff, 0x82, 0xa3, 0x63, 0xbe, 0x1e, 0x9e, 0x40, 0x55, 0x9a,
0x05, 0x8b, 0x93, 0x4d, 0xbd, 0x65, 0xde, 0x59, 0x88, 0x25, 0x2c, 0x1f, 0x06, 0x67, 0x87, 0xf9,
0x00, 0x7a, 0x71, 0x56, 0xdc, 0x99, 0xa9, 0x93, 0x9e, 0x32, 0xef, 0x2e, 0x89, 0x26, 0x8c, 0x1c,
0x08, 0x9e, 0x41, 0x76, 0x0b, 0x9e, 0x38, 0xf1, 0xc4, 0xbe, 0x4e, 0x53, 0x26, 0xc7, 0x6b, 0x9f,
0xe4, 0xff, 0x41, 0x57, 0x13, 0x0b, 0x1e, 0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0x88, 0xff, 0xa1,
0x0a, 0x32, 0x06, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -638,7 +639,7 @@ func NewGrpcClient(cc *grpc.ClientConn) GrpcClient {
func (c *grpcClient) Create(ctx context.Context, in *CreateReq, opts ...grpc.CallOption) (*CreateRsp, error) {
out := new(CreateRsp)
err := c.cc.Invoke(ctx, "/grpcserver.grpc/Create", in, out, opts...)
err := c.cc.Invoke(ctx, "/public.grpc/Create", in, out, opts...)
if err != nil {
return nil, err
}
@ -647,7 +648,7 @@ func (c *grpcClient) Create(ctx context.Context, in *CreateReq, opts ...grpc.Cal
func (c *grpcClient) Update(ctx context.Context, in *UpdateReq, opts ...grpc.CallOption) (*empty.Empty, error) {
out := new(empty.Empty)
err := c.cc.Invoke(ctx, "/grpcserver.grpc/Update", in, out, opts...)
err := c.cc.Invoke(ctx, "/public.grpc/Update", in, out, opts...)
if err != nil {
return nil, err
}
@ -656,7 +657,7 @@ func (c *grpcClient) Update(ctx context.Context, in *UpdateReq, opts ...grpc.Cal
func (c *grpcClient) Delete(ctx context.Context, in *DeleteReq, opts ...grpc.CallOption) (*empty.Empty, error) {
out := new(empty.Empty)
err := c.cc.Invoke(ctx, "/grpcserver.grpc/Delete", in, out, opts...)
err := c.cc.Invoke(ctx, "/public.grpc/Delete", in, out, opts...)
if err != nil {
return nil, err
}
@ -665,7 +666,7 @@ func (c *grpcClient) Delete(ctx context.Context, in *DeleteReq, opts ...grpc.Cal
func (c *grpcClient) List(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ListResp, error) {
out := new(ListResp)
err := c.cc.Invoke(ctx, "/grpcserver.grpc/List", in, out, opts...)
err := c.cc.Invoke(ctx, "/public.grpc/List", in, out, opts...)
if err != nil {
return nil, err
}
@ -674,7 +675,7 @@ func (c *grpcClient) List(ctx context.Context, in *empty.Empty, opts ...grpc.Cal
func (c *grpcClient) GetByID(ctx context.Context, in *GetByIDReq, opts ...grpc.CallOption) (*GetByIDResp, error) {
out := new(GetByIDResp)
err := c.cc.Invoke(ctx, "/grpcserver.grpc/GetByID", in, out, opts...)
err := c.cc.Invoke(ctx, "/public.grpc/GetByID", in, out, opts...)
if err != nil {
return nil, err
}
@ -683,7 +684,7 @@ func (c *grpcClient) GetByID(ctx context.Context, in *GetByIDReq, opts ...grpc.C
func (c *grpcClient) GetByDate(ctx context.Context, in *GetByDateReq, opts ...grpc.CallOption) (*GetByDateResp, error) {
out := new(GetByDateResp)
err := c.cc.Invoke(ctx, "/grpcserver.grpc/GetByDate", in, out, opts...)
err := c.cc.Invoke(ctx, "/public.grpc/GetByDate", in, out, opts...)
if err != nil {
return nil, err
}
@ -737,7 +738,7 @@ func _Grpc_Create_Handler(srv interface{}, ctx context.Context, dec func(interfa
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpcserver.grpc/Create",
FullMethod: "/public.grpc/Create",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).Create(ctx, req.(*CreateReq))
@ -755,7 +756,7 @@ func _Grpc_Update_Handler(srv interface{}, ctx context.Context, dec func(interfa
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpcserver.grpc/Update",
FullMethod: "/public.grpc/Update",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).Update(ctx, req.(*UpdateReq))
@ -773,7 +774,7 @@ func _Grpc_Delete_Handler(srv interface{}, ctx context.Context, dec func(interfa
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpcserver.grpc/Delete",
FullMethod: "/public.grpc/Delete",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).Delete(ctx, req.(*DeleteReq))
@ -791,7 +792,7 @@ func _Grpc_List_Handler(srv interface{}, ctx context.Context, dec func(interface
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpcserver.grpc/List",
FullMethod: "/public.grpc/List",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).List(ctx, req.(*empty.Empty))
@ -809,7 +810,7 @@ func _Grpc_GetByID_Handler(srv interface{}, ctx context.Context, dec func(interf
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpcserver.grpc/GetByID",
FullMethod: "/public.grpc/GetByID",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).GetByID(ctx, req.(*GetByIDReq))
@ -827,7 +828,7 @@ func _Grpc_GetByDate_Handler(srv interface{}, ctx context.Context, dec func(inte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/grpcserver.grpc/GetByDate",
FullMethod: "/public.grpc/GetByDate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GrpcServer).GetByDate(ctx, req.(*GetByDateReq))
@ -836,7 +837,7 @@ func _Grpc_GetByDate_Handler(srv interface{}, ctx context.Context, dec func(inte
}
var _Grpc_serviceDesc = grpc.ServiceDesc{
ServiceName: "grpcserver.grpc",
ServiceName: "public.grpc",
HandlerType: (*GrpcServer)(nil),
Methods: []grpc.MethodDesc{
{

View File

@ -2,11 +2,11 @@
// source: grpcserver.proto
/*
Package grpcserver is a reverse proxy.
Package public is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package grpcserver
package public
import (
"io"

View File

@ -1,17 +1,17 @@
package grpcserver
package public
import (
"context"
"github.com/golang/protobuf/ptypes/empty"
"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/storage/event"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/calendar"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage/event"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type Service struct {
App app.App
App calendar.App
}
func (s Service) Create(ctx context.Context, e *CreateReq) (*CreateRsp, error) {

View File

@ -1,19 +1,24 @@
package grpcserver
package public
import (
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/stretchr/testify/suite"
"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"
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/calendar"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/logger"
store "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage"
oslog "log"
"testing"
"time"
)
var conf = config.Config{HTTP: config.Server{Address: "localhost", Port: "50511"}, GRPC: config.Server{Address: "localhost", Port: "50512"}, Logger: config.Logger{File: "calendar.log", Level: "INFO", MuteStdout: false}, Storage: config.Storage{InMemory: true, SQLHost: "", SQLPort: "", SQLDbase: "", SQLUser: "", SQLPass: ""}}
var conf = config.Calendar{
HTTP: config.Server{Address: "localhost", Port: "50511"},
GRPC: config.Server{Address: "localhost", Port: "50512"},
API: config.Server{Address: "localhost", Port: "50513"},
Logger: config.Logger{File: "calendar.log", Level: "INFO", MuteStdout: false},
Storage: config.Storage{InMemory: true, SQLHost: "", SQLPort: "", SQLDbase: "", SQLUser: "", SQLPass: ""}}
var storeConf = store.Config(conf.Storage)
@ -31,11 +36,11 @@ type TestSuite struct {
}
func (suite *TestSuite) SetupTest() {
log, err := logger.New(conf)
log, err := logger.New(logger.Config(conf.Logger))
if err != nil {
oslog.Fatal("can't init logger")
}
suite.srv = Service{App: *app.New(log, store.NewStore(storeConf))}
suite.srv = Service{App: *calendar.New(log, store.NewStore(storeConf))}
}
func (s *TestSuite) TestCreateEvent() {
@ -74,7 +79,7 @@ func (s *TestSuite) TestListEvent() {
s.createEvent(&testEvent)
eventList := s.listEvents()
s.GreaterOrEqual(len(eventList),1)
s.GreaterOrEqual(len(eventList), 1)
s.Equal(testEvt1.Title, eventList[0].Title)
}
@ -91,7 +96,7 @@ func (s *TestSuite) TestGetEventByDate() {
s.createEvent(&testEvent)
eventList := s.getEventByDate(testEvent.Date)
s.GreaterOrEqual(len(eventList),1)
s.GreaterOrEqual(len(eventList), 1)
s.Equal(testEvent.Title, eventList[0].Title)
}

View File

@ -1,23 +1,23 @@
package grpcserver
package public
import (
"net"
"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/calendar"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/config"
googrpc "google.golang.org/grpc"
)
type Server struct {
s *googrpc.Server
app app.App
app calendar.App
}
func New(app *app.App) Server {
func New(app *calendar.App) Server {
return Server{s: googrpc.NewServer(), app: *app}
}
func (s *Server) Start(conf config.Config) error {
func (s *Server) Start(conf config.Calendar) error {
s.app.Logger.Infof("GRPC server starting")
listnGrpc, err := net.Listen("tcp", net.JoinHostPort(conf.GRPC.Address, conf.GRPC.Port))
RegisterGrpcServer(s.s, &Service{})

View File

@ -0,0 +1,22 @@
package config
import (
"io/ioutil"
"os"
"github.com/BurntSushi/toml"
)
func New(configFile string, str interface{}) error {
f, err := os.Open(configFile)
if err != nil {
return err
}
defer f.Close()
s, err := ioutil.ReadAll(f)
if err != nil {
return err
}
_, err = toml.Decode(string(s), str)
return err
}

View File

@ -37,19 +37,22 @@ SQLHost = "localhost"`)
goodfile.Sync()
t.Run("No such file", func(t *testing.T) {
c, e := NewConfig("adfergdth")
require.Equal(t, Config{}, c)
var c Calendar
e := New("adfergdth", &c)
require.Equal(t, Calendar{}, c)
require.Error(t, e)
})
t.Run("Bad file", func(t *testing.T) {
c, e := NewConfig(badfile.Name())
require.Equal(t, Config{}, c)
var c Calendar
e := New(badfile.Name(), &c)
require.Equal(t, Calendar{}, c)
require.Error(t, e)
})
t.Run("TOML reading", func(t *testing.T) {
c, e := NewConfig(goodfile.Name())
var c Calendar
e := New(goodfile.Name(), &c)
require.Equal(t, true, c.Storage.InMemory)
require.Equal(t, "localhost", c.Storage.SQLHost)
require.NoError(t, e)

View File

@ -0,0 +1,50 @@
package config
type Calendar struct {
GRPC Server
HTTP Server
API Server
Logger Logger
Storage Storage
}
type Scheduler struct {
Rabbitmq Rabbit
Storage Storage
Logger Logger
}
type Sender struct {
Rabbitmq Rabbit
Logger Logger
}
type Server struct {
Address string
Port string
}
type Rabbit struct {
Login string
Pass string
Address string
Port string
Exchange string
Queue string
Key string
}
type Logger struct {
File string
Level string
MuteStdout bool
}
type Storage struct {
InMemory bool
SQLHost string
SQLPort string
SQLDbase string
SQLUser string
SQLPass string
}

View File

@ -7,7 +7,6 @@ import (
"strings"
amitralog "github.com/amitrai48/logger"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config"
)
type Interface interface {
@ -22,21 +21,27 @@ type Logger struct {
Logger amitralog.Logger
}
type Config struct {
File string
Level string
MuteStdout bool
}
var validLevel = map[string]bool{"debug": true, "info": true, "warn": true, "error": true, "fatal": true}
func New(conf config.Config) (Interface, error) {
if conf.Logger.File == "" || !validLevel[strings.ToLower(conf.Logger.Level)] {
func New(conf Config) (Interface, error) {
if conf.File == "" || !validLevel[strings.ToLower(conf.Level)] {
return nil, errors.New("invalid logger config")
}
c := amitralog.Configuration{
EnableConsole: !conf.Logger.MuteStdout,
EnableConsole: !conf.MuteStdout,
ConsoleLevel: amitralog.Fatal,
ConsoleJSONFormat: false,
EnableFile: true,
FileLevel: strings.ToLower(conf.Logger.Level),
FileLevel: strings.ToLower(conf.Level),
FileJSONFormat: true,
FileLocation: conf.Logger.File,
FileLocation: conf.File,
}
if err := amitralog.NewLogger(c, amitralog.InstanceZapLogger); err != nil {

View File

@ -2,7 +2,6 @@ package logger
import (
"github.com/stretchr/testify/require"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/internal/config"
"io/ioutil"
oslog "log"
"os"
@ -17,11 +16,7 @@ func TestLoggerLogic(t *testing.T) {
}
defer os.Remove(tmpfile.Name())
conf := config.Config{Logger: struct {
File string
Level string
MuteStdout bool
}{File: tmpfile.Name(), Level: "warn", MuteStdout: false}}
conf := Config{File: tmpfile.Name(), Level: "warn", MuteStdout: false}
log, err := New(conf)
if err != nil {
oslog.Fatal(err)
@ -42,21 +37,13 @@ func TestLoggerLogic(t *testing.T) {
func TestLoggerNegative(t *testing.T) {
t.Run("Bad file name", func(t *testing.T) {
conf := config.Config{Logger: struct {
File string
Level string
MuteStdout bool
}{File: "", Level: "debug", MuteStdout: true}}
conf := Config{File: "", Level: "debug", MuteStdout: true}
_, err := New(conf)
require.Error(t, err, "invalid logger config")
})
t.Run("Bad level", func(t *testing.T) {
conf := config.Config{Logger: struct {
File string
Level string
MuteStdout bool
}{File: "asdafad", Level: "wegretryjt", MuteStdout: true}}
conf := Config{File: "asdafad", Level: "wegretryjt", MuteStdout: true}
_, err := New(conf)
require.Error(t, err, "invalid logger config")
})

View File

@ -0,0 +1,52 @@
package rabbit
import (
"context"
"fmt"
"log"
"github.com/streadway/amqp"
)
type RMQConnection interface {
Channel() (*amqp.Channel, error)
}
type Message struct {
Ctx context.Context
Data []byte
}
func (r *Rabbit) Consume(ctx context.Context, queue string) (<-chan Message, error) {
messages := make(chan Message)
deliveries, err := r.Channel.Consume(queue, "", false, false, false, false, nil)
if err != nil {
return nil, fmt.Errorf("start consuming: %w", err)
}
go func() {
for {
select {
case <-ctx.Done():
return
case del := <-deliveries:
if err := del.Ack(false); err != nil {
log.Println(err)
}
msg := Message{
Ctx: context.TODO(),
Data: del.Body,
}
select {
case <-ctx.Done():
return
case messages <- msg:
}
}
}
}()
return messages, nil
}

View File

@ -0,0 +1,27 @@
package rabbit
import (
"encoding/json"
"github.com/streadway/amqp"
)
func (r *Rabbit) Publish(body string) error {
b, err := json.Marshal([]byte(body))
if err != nil {
return err
}
err = r.Channel.Publish(
r.Exchange, // exchange
r.Key, // routing key
false, // mandatory
false, // immediate
amqp.Publishing{
ContentType: "application/json; charset=utf-8",
Body: b,
})
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,84 @@
package rabbit
import (
"github.com/streadway/amqp"
)
type Rabbit struct {
Connection *amqp.Connection
Channel *amqp.Channel
Exchange string
Key string
Queue string
}
type Config struct {
Login string
Pass string
Address string
Port string
Exchange string
Queue string
Key string
}
func New(conf Config) (*Rabbit, error) {
conn, err := amqp.Dial("amqp://" + conf.Login + ":" + conf.Pass + "@" + conf.Address + ":" + conf.Port + "/")
if err != nil {
return nil, err
}
ch, err := conn.Channel()
if err != nil {
return nil, err
}
err = ch.ExchangeDeclare(
conf.Exchange, // name
"direct", // type
true, // durable
false, // auto-deleted
false, // internal
false, // no-wait
nil, // arguments
)
if err != nil {
return nil, err
}
q, err := ch.QueueDeclare(
conf.Queue,
false,
false,
false,
false,
nil,
)
if err != nil {
return nil, err
}
err = ch.QueueBind(q.Name, conf.Key, conf.Exchange, false, nil)
if err != nil {
return nil, err
}
return &Rabbit{Connection: conn, Channel: ch}, nil
}
func Attach(conf Config) (*Rabbit, error) {
conn, err := amqp.Dial("amqp://" + conf.Login + ":" + conf.Pass + "@" + conf.Address + ":" + conf.Port + "/")
if err != nil {
return nil, err
}
ch, err := conn.Channel()
if err != nil {
return nil, err
}
return &Rabbit{Connection: conn, Channel: ch, Exchange: conf.Exchange, Queue: conf.Queue, Key: conf.Key}, nil
}
func (r *Rabbit) Close() error {
if err := r.Channel.Close(); err != nil {
return err
}
if err := r.Connection.Close(); err != nil {
return err
}
return nil
}

View File

@ -13,4 +13,5 @@ type Event struct {
Note string
UserID int64
NotifyTime time.Duration
Notified bool
}

View File

@ -4,7 +4,7 @@ import (
"sync"
"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/pkg/storage/event"
)
type Storage struct {
@ -65,6 +65,27 @@ func (s *Storage) GetByDate(startDate time.Time, rng string) (map[event.ID]event
return res, nil
}
func (s *Storage) GetNotifications() (map[event.ID]event.Event, error) {
s.Mu.Lock()
defer s.Mu.Unlock()
res := make(map[event.ID]event.Event)
for k, v := range s.Events {
if time.Until(v.Date) <= v.NotifyTime && !v.Notified {
res[k] = v
}
}
return res, nil
}
func (s *Storage) SetNotified(id event.ID) error {
s.Mu.Lock()
tmp := s.Events[id]
tmp.Notified = true
s.Events[id] = tmp
s.Mu.Unlock()
return nil
}
func getEndDate(startDate time.Time, rng string) time.Time {
switch rng {
case "DAY":

View File

@ -2,7 +2,7 @@ package memory
import (
"github.com/stretchr/testify/require"
"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/pkg/storage/event"
"testing"
"time"
)

View File

@ -4,7 +4,7 @@ import (
"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/pkg/storage/event"
)
const dateTimeLayout = "2006-01-02 15:04:00 -0700"
@ -159,6 +159,48 @@ func (s *Storage) GetByDate(startDate time.Time, rng string) (map[event.ID]event
return res, nil
}
func (s *Storage) GetNotifications() (map[event.ID]event.Event, error) {
res := make(map[event.ID]event.Event)
results, err := s.db.Query(
`SELECT (id,title,date,latency,note,userID,notifyTime)
from events
where ($1>date-notifyTime) AND (NOT notified)
ORDER BY id`,
time.Now())
if err != nil {
return nil, err
}
defer results.Close()
for results.Next() {
var id event.ID
var evt event.Event
var dateRaw string
err = results.Scan(&id, &evt.Title, &dateRaw, &evt.Latency, &evt.Note, &evt.UserID, &evt.NotifyTime)
if err != nil {
return nil, err
}
evt.Date, err = time.Parse(dateTimeLayout, dateRaw)
if err != nil {
return nil, err
}
res[id] = evt
}
if results.Err() != nil {
return nil, results.Err()
}
return res, nil
}
func (s *Storage) SetNotified(id event.ID) error {
_, err := s.db.Exec(
`UPDATE events set
notified=true
where id=$1`,
id,
)
return err
}
func getEndDate(startDate time.Time, rng string) time.Time {
switch rng {
case "DAY":

View File

@ -3,9 +3,9 @@ package store
import (
"time"
"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"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage/event"
memorystorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage/memory"
sqlstorage "github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/pkg/storage/sql"
)
type Config struct {
@ -24,6 +24,8 @@ type StorageInterface interface {
List() (map[event.ID]event.Event, error)
GetByID(event.ID) (event.Event, bool)
GetByDate(time.Time, string) (map[event.ID]event.Event, error)
GetNotifications() (map[event.ID]event.Event, error)
SetNotified(event.ID) error
}
func NewStore(conf Config) StorageInterface {