hw12_13_14_15_calendar
Andrey Ivanov 2021-03-22 13:03:12 -04:00 committed by Andrey Ivanov
parent bb3e580e67
commit 1c4ba38acf
13 changed files with 119 additions and 159 deletions

View File

@ -58,6 +58,7 @@ message Event {
string Note = 5;
int64 UserID = 6;
google.protobuf.Duration NotifyTime = 7;
bool notified = 8;
}
message CreateReq {

View File

@ -15,6 +15,8 @@ services:
APP_RABBITMQ_EXCHANGE: calendar
APP_RABBITMQ_QUEUE: notifications
APP_RABBITMQ_KEY: events
APP_API_ADDRESS: localhost
APP_API_PORT: 50053
APP_LOGGER_FILE: /logs/calendar.log
APP_LOGGER_LEVEL: INFO
network_mode: host

View File

@ -148,101 +148,6 @@ func TestPublicGRPCEndpoint(t *testing.T) {
wg.Wait()
}
func TestPublicAPIEndpoint(t *testing.T) {
wg := sync.WaitGroup{}
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
publicAPI, err := public.NewClient(ctx, "localhost", "50051")
require.NoError(t, err)
wg.Add(5)
// Реализовать тесты логики приложения:
t.Run("test public GRPC.Create and GRPC.GetById", func(t *testing.T) {
defer wg.Done()
resp1, err := publicAPI.Create(ctx, &testEvent01)
require.NoError(t, err)
require.Greater(t, resp1.ID, int64(0))
resp2, err := publicAPI.GetByID(ctx, &public.GetByIDReq{ID: resp1.ID})
require.NoError(t, err)
require.Equal(t, 1, len(resp2.Events))
require.Equal(t, testEvent01.Title, resp2.Events[0].Title)
require.Equal(t, testEvent01.UserID, resp2.Events[0].UserID)
require.Equal(t, testEvent01.Date.Seconds, resp2.Events[0].Date.Seconds)
require.Equal(t, testEvent01.Note, resp2.Events[0].Note)
})
t.Run("test public GRPC.Create, GRPC.Update and GRPC.GetById", func(t *testing.T) {
defer wg.Done()
resp1, err := publicAPI.Create(ctx, &testEvent01)
require.NoError(t, err)
require.Greater(t, resp1.ID, int64(0))
_, err = publicAPI.Update(ctx, &public.UpdateReq{ID: resp1.ID, Event: &public.Event{ID: resp1.ID, Title: testEvent02.Title, Date: testEvent02.Date, Latency: testEvent02.Latency, Note: testEvent02.Note, UserID: testEvent02.UserID, NotifyTime: testEvent02.NotifyTime}})
require.NoError(t, err)
resp2, err := publicAPI.GetByID(ctx, &public.GetByIDReq{ID: resp1.ID})
require.NoError(t, err)
require.Equal(t, 1, len(resp2.Events))
require.Equal(t, testEvent02.Title, resp2.Events[0].Title)
require.Equal(t, testEvent02.UserID, resp2.Events[0].UserID)
require.Equal(t, testEvent02.Date.Seconds, resp2.Events[0].Date.Seconds)
require.Equal(t, testEvent02.Note, resp2.Events[0].Note)
})
t.Run("test public GRPC.Create, GRPC.Delete and GRPC.GetById", func(t *testing.T) {
defer wg.Done()
resp1, err := publicAPI.Create(ctx, &testEvent01)
require.NoError(t, err)
require.Greater(t, resp1.ID, int64(0))
_, err = publicAPI.Delete(ctx, &public.DeleteReq{ID: resp1.ID})
require.NoError(t, err)
resp2, err := publicAPI.GetByID(ctx, &public.GetByIDReq{ID: resp1.ID})
require.Error(t, err)
require.Nil(t, resp2)
})
t.Run("test public GRPC.Create and GRPC.List", func(t *testing.T) {
defer wg.Done()
resp1, err := publicAPI.Create(ctx, &testEvent01)
require.NoError(t, err)
resp2, err := publicAPI.Create(ctx, &testEvent02)
require.NoError(t, err)
require.NotEqual(t, resp1.ID, resp2.ID)
list, err := publicAPI.List(ctx, &empty.Empty{})
require.NoError(t, err)
require.GreaterOrEqual(t, len(list.Events), 2)
var e1, e2 bool
for _, v := range list.Events {
if v.ID == resp1.ID {
e1 = true
}
if v.ID == resp2.ID {
e2 = true
}
}
require.True(t, e1)
require.True(t, e2)
})
t.Run("test public GRPC.Create and GRPC.GetByDate", func(t *testing.T) {
defer wg.Done()
resp1, err := publicAPI.Create(ctx, &testEvent01)
require.NoError(t, err)
list, err := publicAPI.GetByDate(ctx, &public.GetByDateReq{Date: testEvent01.Date, Range: public.QueryRange_DAY})
require.NoError(t, err)
require.GreaterOrEqual(t, len(list.Events), 2)
var e1 bool
for _, v := range list.Events {
if v.ID == resp1.ID {
e1 = true
}
}
require.True(t, e1)
})
wg.Wait()
}
func time2pbtimestamp(t time.Time) *timestamp.Timestamp {
r, err := ptypes.TimestampProto(t)
if err != nil {

View File

@ -15,7 +15,7 @@ File = "./logs/calendar.log"
Level = "INFO"
[Storage]
inMemory = true
inMemory = false
SQLHost = "localhost"
SQLPort = "5432"
SQLDbase = "calendar"

View File

@ -11,6 +11,6 @@ Key = "events"
File = "./logs/calendar.log"
Level = "INFO"
[API]
[CalendarAPI]
Address = "localhost"
Port = "50053"

View File

@ -9,4 +9,8 @@ Key = "events"
[Logger]
File = "./logs/calendar.log"
Level = "INFO"
Level = "INFO"
[API]
Address = "localhost"
Port = "50053"

View File

@ -13,15 +13,17 @@ import (
)
type Sender struct {
Logger logger.Interface
Rabbit *rabbit.Rabbit
Queue string
Stop context.CancelFunc
GRPCAPI private.GrpcClient
Logger logger.Interface
Rabbit *rabbit.Rabbit
Queue string
Stop context.CancelFunc
}
type Config struct {
Rabbitmq config.Rabbit
Logger config.Logger
CalendarAPI config.Server
Rabbitmq config.Rabbit
Logger config.Logger
}
func New(conf Config) Sender {
@ -33,7 +35,11 @@ func New(conf Config) Sender {
if err != nil {
log.Fatalf("failed to connect to RabbitMQ:", err.Error())
}
return Sender{Logger: log, Rabbit: rb, Queue: conf.Rabbitmq.Queue}
cli, err := private.NewClient(conf.CalendarAPI.Address, conf.CalendarAPI.Port)
if err != nil {
log.Fatalf("can't get GRPC client: %w", err.Error())
}
return Sender{Logger: log, Rabbit: rb, Queue: conf.Rabbitmq.Queue, GRPCAPI: cli}
}
func (s *Sender) Start() error {
@ -54,6 +60,10 @@ func (s *Sender) Start() error {
s.Logger.Errorf("can`t unmarshal data %w", err)
}
for _, v := range data {
_, err = s.GRPCAPI.SetNotified(ctx, &private.SetReq{ID: v.ID})
if err != nil {
s.Logger.Errorf("can`t mark event with ID %d as notified data %w", v.ID, err)
}
s.Logger.Infof("User %s notified about event %s", v.UserID, v.ID)
}
case <-ctx.Done():

View File

@ -39,7 +39,7 @@ func New(conf Config) Scheduler {
func (s *Scheduler) Start() error {
ctx, cancel := context.WithCancel(context.Background())
s.Stop = cancel
fetcher := riseOnTick(ctx, s.Logger, func() interface{} { return worker(ctx, s.CalendarAPI, s.Rabbit, s.Logger) }, 1*time.Minute)
fetcher := riseOnTick(ctx, s.Logger, func() interface{} { return worker(ctx, s.CalendarAPI, s.Rabbit, s.Logger) }, 10*time.Second)
go func() {
for {
select {

View File

@ -6,6 +6,7 @@ import (
"fmt"
"time"
"github.com/golang/protobuf/ptypes/empty"
"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"
@ -43,11 +44,11 @@ func worker(ctx context.Context, calendarAPI config.Server, rb *rabbit.Rabbit, l
if err != nil {
return fmt.Errorf("can't get GRPC client: %w", err)
}
resp, err := cli.GetNotifications(ctx, nil)
resp, err := cli.GetNotifications(ctx, &empty.Empty{})
if err != nil {
return fmt.Errorf("can't get events from GRPC endpoint: %w", err)
}
for event := range resp.Events {
for _, event := range resp.Events {
b, err := json.Marshal(event)
if err != nil {
return fmt.Errorf("can't marshal events into JSON: %w", err)

View File

@ -64,6 +64,7 @@ type Event struct {
Note string `protobuf:"bytes,5,opt,name=Note,proto3" json:"Note,omitempty"`
UserID int64 `protobuf:"varint,6,opt,name=UserID,proto3" json:"UserID,omitempty"`
NotifyTime *duration.Duration `protobuf:"bytes,7,opt,name=NotifyTime,proto3" json:"NotifyTime,omitempty"`
Notified bool `protobuf:"varint,8,opt,name=notified,proto3" json:"notified,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -143,6 +144,13 @@ func (m *Event) GetNotifyTime() *duration.Duration {
return nil
}
func (m *Event) GetNotified() bool {
if m != nil {
return m.Notified
}
return false
}
type CreateReq struct {
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"`
@ -567,45 +575,46 @@ func init() {
func init() { proto.RegisterFile("public.proto", fileDescriptor_413a91106d7bcce8) }
var fileDescriptor_413a91106d7bcce8 = []byte{
// 606 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x95, 0xcd, 0x6e, 0xd3, 0x40,
0x10, 0xc7, 0x71, 0xe2, 0x38, 0xf5, 0x34, 0x2d, 0xe9, 0x50, 0x8a, 0x71, 0xab, 0x12, 0x2d, 0x42,
// 619 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x95, 0xcd, 0x6e, 0xd3, 0x40,
0x10, 0xc7, 0xb1, 0xe3, 0x38, 0xf6, 0x34, 0x2d, 0xe9, 0x50, 0x8a, 0x71, 0xab, 0x12, 0x2d, 0x42,
0x8a, 0x72, 0xb0, 0x45, 0x8a, 0x90, 0xe0, 0x44, 0x8b, 0x23, 0x6a, 0x51, 0x8a, 0xb0, 0x5a, 0xf1,
0x71, 0x73, 0xd2, 0x6d, 0xb0, 0x94, 0xd8, 0x8b, 0xbd, 0x41, 0x8a, 0xaa, 0x5c, 0x78, 0x05, 0xde,
0x8a, 0x2b, 0xaf, 0xc0, 0x95, 0x07, 0xe0, 0x86, 0xbc, 0x5e, 0x3b, 0xcd, 0x47, 0x45, 0xee, 0xdc,
0xb2, 0xfb, 0x9f, 0xf9, 0xcd, 0xcc, 0xce, 0x5f, 0x31, 0xd4, 0xd8, 0xa8, 0x3b, 0x08, 0x7a, 0x16,
0x8b, 0x23, 0x1e, 0xa1, 0x96, 0x9d, 0xcc, 0x07, 0xfd, 0x28, 0xea, 0x0f, 0xa8, 0x2d, 0x6e, 0xbb,
0xa3, 0x4b, 0x9b, 0x07, 0x43, 0x9a, 0x70, 0x7f, 0xc8, 0xb2, 0x40, 0x73, 0x7f, 0x3e, 0xe0, 0x62,
0x14, 0xfb, 0x3c, 0x88, 0x42, 0xa9, 0xef, 0xce, 0xeb, 0x74, 0xc8, 0xf8, 0x58, 0x8a, 0x7b, 0x52,
0xf4, 0x59, 0x60, 0xfb, 0x61, 0x18, 0x71, 0x91, 0x99, 0x64, 0x2a, 0xf9, 0xa3, 0x40, 0xa5, 0xf3,
0x95, 0x86, 0x1c, 0x37, 0xa1, 0xe4, 0x3a, 0x86, 0xd2, 0x50, 0x9a, 0x65, 0xaf, 0xe4, 0x3a, 0xb8,
0x0d, 0x95, 0xb3, 0x80, 0x0f, 0xa8, 0x51, 0x6a, 0x28, 0x4d, 0xdd, 0xcb, 0x0e, 0x68, 0x81, 0xea,
0xf8, 0x9c, 0x1a, 0xe5, 0x86, 0xd2, 0x5c, 0x6f, 0x9b, 0x56, 0x06, 0xb7, 0xf2, 0xca, 0xd6, 0x59,
0xde, 0xba, 0x27, 0xe2, 0xf0, 0x00, 0xaa, 0x27, 0x3e, 0xa7, 0x61, 0x6f, 0x6c, 0xa8, 0x22, 0xe5,
0xfe, 0x42, 0x8a, 0x23, 0x87, 0xf1, 0xf2, 0x48, 0x44, 0x50, 0x4f, 0x23, 0x4e, 0x8d, 0x8a, 0xa8,
0x2c, 0x7e, 0xe3, 0x0e, 0x68, 0xe7, 0x09, 0x8d, 0x5d, 0xc7, 0xd0, 0x44, 0x8b, 0xf2, 0x84, 0xcf,
0x00, 0x4e, 0x23, 0x1e, 0x5c, 0x8e, 0xd3, 0xca, 0x46, 0xf5, 0x5f, 0x35, 0xae, 0x05, 0x93, 0xdf,
0x0a, 0xe8, 0x2f, 0x63, 0xea, 0x73, 0xea, 0xd1, 0x2f, 0xff, 0xc1, 0xbc, 0xbb, 0xc5, 0xb8, 0x09,
0x9b, 0x5f, 0x37, 0x79, 0x01, 0xfa, 0x39, 0xbb, 0x90, 0x6f, 0x31, 0xef, 0x85, 0x87, 0xd2, 0x24,
0xe2, 0x6d, 0xd6, 0xdb, 0x1b, 0x96, 0xf4, 0xb1, 0xb8, 0xf4, 0x32, 0x2d, 0xc5, 0x3b, 0x74, 0x40,
0x97, 0x12, 0xc8, 0x63, 0x58, 0x3b, 0x09, 0x12, 0xee, 0xd1, 0x84, 0xe1, 0x23, 0xd0, 0x44, 0x46,
0x62, 0x28, 0x8d, 0xf2, 0x22, 0x4e, 0x8a, 0x64, 0x0f, 0xe0, 0x15, 0xe5, 0x47, 0x63, 0xd7, 0x59,
0x06, 0x7c, 0x02, 0xeb, 0x85, 0xba, 0x3a, 0xf3, 0x33, 0xd4, 0x44, 0x96, 0x23, 0x07, 0xcd, 0xd7,
0xab, 0xac, 0xb8, 0xde, 0x26, 0x54, 0x3c, 0x3f, 0xec, 0x67, 0x26, 0xd9, 0x6c, 0x63, 0x5e, 0xe5,
0xdd, 0x88, 0xc6, 0x63, 0xa1, 0x78, 0x59, 0x00, 0x79, 0x0a, 0x1b, 0xd7, 0x2a, 0xad, 0xdc, 0x61,
0xab, 0x05, 0x30, 0x85, 0x61, 0x15, 0xca, 0xce, 0xe1, 0xc7, 0xfa, 0x2d, 0x5c, 0x03, 0xf5, 0x7d,
0xa7, 0xf3, 0xba, 0xae, 0xa0, 0x0e, 0x95, 0x37, 0x6f, 0x4f, 0xcf, 0x8e, 0xeb, 0xa5, 0xf6, 0x8f,
0x32, 0xa8, 0xfd, 0x98, 0xf5, 0xf0, 0x08, 0xb4, 0x6c, 0xb3, 0xb8, 0x95, 0x53, 0x0b, 0x63, 0x9b,
0xf3, 0x57, 0x09, 0x23, 0xf8, 0xed, 0xe7, 0xaf, 0xef, 0xa5, 0x1a, 0xa9, 0xda, 0x54, 0x54, 0x7d,
0xae, 0xb4, 0xf0, 0x04, 0xb4, 0xcc, 0x00, 0x53, 0x46, 0x61, 0x08, 0x73, 0x67, 0xe1, 0x65, 0x3a,
0xe9, 0x5f, 0x0c, 0xb9, 0x27, 0x40, 0x5b, 0x66, 0x4d, 0x82, 0xec, 0x2b, 0xd7, 0x99, 0xa4, 0x34,
0x17, 0xb4, 0xcc, 0x0c, 0x53, 0x5a, 0x61, 0x8e, 0x1b, 0x69, 0xdb, 0x82, 0xb6, 0xd9, 0x9a, 0xa1,
0xe1, 0x21, 0xa8, 0xa9, 0x75, 0xf0, 0x86, 0x2c, 0xb3, 0x9e, 0x17, 0xc8, 0x0d, 0x46, 0x6e, 0x0b,
0x8e, 0x8e, 0xf9, 0x78, 0x78, 0x0c, 0x55, 0x69, 0x16, 0x2c, 0x56, 0x36, 0xf5, 0x96, 0x79, 0x67,
0xe1, 0x2e, 0x61, 0x79, 0x33, 0x38, 0xdb, 0xcc, 0x07, 0xd0, 0x8b, 0xb5, 0xe2, 0xf6, 0x4c, 0x9e,
0xf4, 0x94, 0x79, 0x77, 0xc9, 0x6d, 0xc2, 0xc8, 0xbe, 0xe0, 0x19, 0x64, 0xa7, 0xe0, 0x89, 0x15,
0x4f, 0xec, 0xab, 0x34, 0x64, 0x72, 0xb4, 0xf6, 0x49, 0x7e, 0x0f, 0xba, 0x9a, 0x18, 0xf0, 0xe0,
0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x37, 0x8b, 0x96, 0x2e, 0x06, 0x00, 0x00,
0x71, 0x73, 0xdb, 0x6d, 0xb0, 0x94, 0xda, 0x8b, 0xbd, 0x41, 0x8a, 0xaa, 0x5e, 0x78, 0x05, 0xc4,
0x4b, 0x71, 0xe5, 0x15, 0xb8, 0xf2, 0x0e, 0xc8, 0xeb, 0xb5, 0xd3, 0x26, 0xa9, 0xc8, 0x99, 0x5b,
0xe6, 0xeb, 0x37, 0x33, 0x3b, 0x7f, 0xc5, 0xd0, 0x64, 0xa3, 0xe3, 0x61, 0x74, 0xe2, 0xb0, 0x34,
0xe1, 0x09, 0xea, 0x85, 0x65, 0x3f, 0x18, 0x24, 0xc9, 0x60, 0x48, 0x5d, 0xe1, 0x3d, 0x1e, 0x9d,
0xb9, 0x3c, 0x3a, 0xa7, 0x19, 0x0f, 0xcf, 0x59, 0x91, 0x68, 0x6f, 0x4d, 0x27, 0x9c, 0x8e, 0xd2,
0x90, 0x47, 0x49, 0x2c, 0xe3, 0x1b, 0xd3, 0x71, 0x7a, 0xce, 0xf8, 0x58, 0x06, 0x37, 0x65, 0x30,
0x64, 0x91, 0x1b, 0xc6, 0x71, 0xc2, 0x45, 0x65, 0x56, 0x44, 0xc9, 0x0f, 0x15, 0xea, 0xfd, 0xaf,
0x34, 0xe6, 0xb8, 0x02, 0xaa, 0xef, 0x59, 0x4a, 0x5b, 0xe9, 0xd4, 0x02, 0xd5, 0xf7, 0x70, 0x0d,
0xea, 0x87, 0x11, 0x1f, 0x52, 0x4b, 0x6d, 0x2b, 0x1d, 0x33, 0x28, 0x0c, 0x74, 0x40, 0xf3, 0x42,
0x4e, 0xad, 0x5a, 0x5b, 0xe9, 0x2c, 0xf5, 0x6c, 0xa7, 0x80, 0x3b, 0x65, 0x67, 0xe7, 0xb0, 0x1c,
0x3d, 0x10, 0x79, 0xb8, 0x0d, 0x8d, 0xfd, 0x90, 0xd3, 0xf8, 0x64, 0x6c, 0x69, 0xa2, 0xe4, 0xfe,
0x4c, 0x89, 0x27, 0x97, 0x09, 0xca, 0x4c, 0x44, 0xd0, 0x0e, 0x12, 0x4e, 0xad, 0xba, 0xe8, 0x2c,
0x7e, 0xe3, 0x3a, 0xe8, 0x47, 0x19, 0x4d, 0x7d, 0xcf, 0xd2, 0xc5, 0x88, 0xd2, 0xc2, 0x67, 0x00,
0x07, 0x09, 0x8f, 0xce, 0xc6, 0x79, 0x67, 0xab, 0xf1, 0xaf, 0x1e, 0x57, 0x92, 0xd1, 0x06, 0x23,
0xce, 0xad, 0x88, 0x9e, 0x5a, 0x46, 0x5b, 0xe9, 0x18, 0x41, 0x65, 0x93, 0x3f, 0x0a, 0x98, 0x2f,
0x53, 0x1a, 0x72, 0x1a, 0xd0, 0x2f, 0xff, 0xff, 0x5b, 0x90, 0x8d, 0x6a, 0xdd, 0x8c, 0x4d, 0x4b,
0x81, 0xbc, 0x00, 0xf3, 0x88, 0x9d, 0xca, 0xb7, 0x98, 0xd6, 0xc9, 0x43, 0x29, 0x20, 0xf1, 0x36,
0x4b, 0xbd, 0x65, 0x47, 0x6a, 0x5c, 0x38, 0x83, 0x22, 0x96, 0xe3, 0x3d, 0x3a, 0xa4, 0x73, 0x09,
0xe4, 0x31, 0x18, 0xfb, 0x51, 0xc6, 0x03, 0x9a, 0x31, 0x7c, 0x04, 0xba, 0xa8, 0xc8, 0x2c, 0xa5,
0x5d, 0x9b, 0xc5, 0xc9, 0x20, 0xd9, 0x04, 0x78, 0x45, 0xf9, 0xee, 0xd8, 0xf7, 0xe6, 0x01, 0x9f,
0xc0, 0x52, 0x15, 0x5d, 0x9c, 0xf9, 0x19, 0x9a, 0xa2, 0xca, 0x93, 0x8b, 0x96, 0xe7, 0x55, 0x16,
0x3c, 0x6f, 0x07, 0xea, 0x41, 0x18, 0x0f, 0x0a, 0x91, 0xac, 0xf4, 0xb0, 0xec, 0xf2, 0x6e, 0x44,
0xd3, 0xb1, 0x88, 0x04, 0x45, 0x02, 0x79, 0x0a, 0xcb, 0x57, 0x3a, 0x2d, 0x3c, 0x61, 0xb7, 0x0b,
0x30, 0x81, 0x61, 0x03, 0x6a, 0xde, 0xce, 0xc7, 0xd6, 0x2d, 0x34, 0x40, 0x7b, 0xdf, 0xef, 0xbf,
0x6e, 0x29, 0x68, 0x42, 0xfd, 0xcd, 0xdb, 0x83, 0xc3, 0xbd, 0x96, 0xda, 0xfb, 0x59, 0x03, 0x6d,
0x90, 0xb2, 0x13, 0xdc, 0x05, 0xbd, 0xb8, 0x2c, 0xae, 0x96, 0xd4, 0x4a, 0xd8, 0xf6, 0xb4, 0x2b,
0x63, 0x04, 0xbf, 0xfd, 0xfa, 0xfd, 0x5d, 0x6d, 0x92, 0x86, 0x4b, 0x45, 0xd7, 0xe7, 0x4a, 0x17,
0xf7, 0x41, 0x2f, 0x04, 0x30, 0x61, 0x54, 0x82, 0xb0, 0xd7, 0x67, 0x5e, 0xa6, 0x9f, 0xff, 0xfd,
0x90, 0x7b, 0x02, 0xb4, 0x6a, 0x37, 0x25, 0xc8, 0xbd, 0xf0, 0xbd, 0xcb, 0x9c, 0xe6, 0x83, 0x5e,
0x88, 0x61, 0x42, 0xab, 0xc4, 0x71, 0x23, 0x6d, 0x4d, 0xd0, 0x56, 0xba, 0xd7, 0x68, 0xb8, 0x03,
0x5a, 0x2e, 0x1d, 0xbc, 0xa1, 0xca, 0x6e, 0x95, 0x0d, 0x4a, 0x81, 0x91, 0xdb, 0x82, 0x63, 0x62,
0xb9, 0x1e, 0xee, 0x41, 0x43, 0x8a, 0x05, 0xab, 0x93, 0x4d, 0xb4, 0x65, 0xdf, 0x99, 0xf1, 0x65,
0xac, 0x1c, 0x06, 0xaf, 0x0f, 0xf3, 0x01, 0xcc, 0xea, 0xac, 0xb8, 0x76, 0xad, 0x4e, 0x6a, 0xca,
0xbe, 0x3b, 0xc7, 0x9b, 0x31, 0xb2, 0x25, 0x78, 0x16, 0x59, 0xaf, 0x78, 0xe2, 0xc4, 0x97, 0xee,
0x45, 0x9e, 0x72, 0xb9, 0x6b, 0x7c, 0x92, 0xdf, 0x8a, 0x63, 0x5d, 0x2c, 0xb8, 0xfd, 0x37, 0x00,
0x00, 0xff, 0xff, 0xef, 0xf0, 0x80, 0xc3, 0x4a, 0x06, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View File

@ -41,14 +41,15 @@ func (s *Storage) Create(ev event.Event) (event.ID, error) {
lastInsertID := -1
if err := s.db.QueryRow(
`INSERT INTO events
(title, date, latency, note, userID, notifyTime) VALUES
($1, $2, $3, $4, $5, $6) RETURNING id`,
(title, date, latency, note, userID, notifyTime,notified) VALUES
($1, $2, $3, $4, $5, $6, $7) RETURNING id`,
ev.Title,
ev.Date.Format(dateTimeLayout),
ev.Latency,
ev.Note,
ev.UserID,
ev.NotifyTime,
false,
).Scan(&lastInsertID); err != nil {
return -1, fmt.Errorf("can't create event in SQL DB: %w", err)
}
@ -87,7 +88,7 @@ func (s *Storage) Delete(id event.ID) error {
func (s *Storage) List() (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 ORDER BY id`)
results, err := s.db.Query(`SELECT id,title,date,latency,note,userID,notifyTime,notified from events ORDER BY id`)
if err != nil {
return nil, fmt.Errorf("can't get list of events from SQL DB: %w", err)
}
@ -96,7 +97,7 @@ func (s *Storage) List() (map[event.ID]event.Event, error) {
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)
err = results.Scan(&id, &evt.Title, &dateRaw, &evt.Latency, &evt.Note, &evt.UserID, &evt.NotifyTime, &evt.Notified)
if err != nil {
return nil, fmt.Errorf("can't parce list of events getted from SQL DB: %w", err)
}
@ -116,7 +117,7 @@ func (s *Storage) GetByID(id event.ID) (event.Event, bool) {
var res event.Event
var dateRaw string
err := s.db.QueryRow(
`SELECT title,date,latency,note,userID,notifyTime from events where id=$1`, id).Scan(&res.Title, &dateRaw, &res.Latency, &res.Note, &res.UserID, &res.NotifyTime)
`SELECT title,date,latency,note,userID,notifyTime,notified from events where id=$1`, id).Scan(&res.Title, &dateRaw, &res.Latency, &res.Note, &res.UserID, &res.NotifyTime, &res.Notified)
if err != nil {
return res, false
}
@ -133,7 +134,7 @@ func (s *Storage) GetByDate(startDate time.Time, rng string) (map[event.ID]event
endDate := getEndDate(startDate, rng)
results, err := s.db.Query(
`SELECT id,title,date,latency,note,userID,notifyTime
`SELECT id,title,date,latency,note,userID,notifyTime,notified
from events
where (date>=$1 AND date<=$2)
ORDER BY id`,
@ -148,7 +149,7 @@ func (s *Storage) GetByDate(startDate time.Time, rng string) (map[event.ID]event
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)
err = results.Scan(&id, &evt.Title, &dateRaw, &evt.Latency, &evt.Note, &evt.UserID, &evt.NotifyTime, &evt.Notified)
if err != nil {
return nil, fmt.Errorf("can't parce list of events getted from SQL DB: %w", err)
}
@ -167,11 +168,10 @@ func (s *Storage) GetByDate(startDate time.Time, rng string) (map[event.ID]event
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)
`SELECT id,title,date,latency,note,userID,notifyTime
from events
where ($1>date-notifyTime) AND (NOT notified)
ORDER BY id`,
time.Now())
where (NOW()>date) AND (NOT notified)
ORDER BY id`)
if err != nil {
return nil, fmt.Errorf("can't get list of events from SQL DB: %w", err)
}

View File

@ -1,11 +1,11 @@
package main
import (
"context"
"github.com/stretchr/testify/require"
"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/test/client"
"github.com/tiburon-777/HW_OTUS/hw12_13_14_15_calendar/test/misc"
"context"
"log"
"sync"
"testing"
@ -18,7 +18,7 @@ func TestPublicAPIEndpoints(t *testing.T) {
client.HTTPAPI{BaseURL: "http://localhost:50052", Name: "HTTP REST API"},
}
wg := sync.WaitGroup{}
wg.Add(len(cli) * 5)
wg.Add(len(cli) * 6)
for _, c := range cli {
t.Run("test "+c.GetName()+" for Create, GetById and Delete", func(t *testing.T) {
@ -153,6 +153,25 @@ func TestPublicAPIEndpoints(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 16, len(resp4.Events))
})
t.Run("test "+c.GetName()+" for send notification", func(t *testing.T) {
var ids []int64
defer func() {
wg.Done()
clean(c, &ids)
}()
resp1, err := c.Create(&misc.TestEvent03)
require.NoError(t, err)
require.Greater(t, resp1.ID, int64(0))
ids = append(ids, resp1.ID)
time.Sleep(3 * time.Second)
resp2, err := c.GetByID(&public.GetByIDReq{ID: resp1.ID})
require.NoError(t, err)
require.Equal(t, 1, len(resp2.Events))
require.True(t, resp2.Events[0].Notified)
})
}
}

View File

@ -27,6 +27,15 @@ var TestEvent02 = public.CreateReq{
UserID: 2222,
}
var TestEvent03 = public.CreateReq{
Title: "Test event 03",
Date: Time2pbtimestamp(time.Now().Add(-5 * time.Minute)),
Latency: Dur2pbduration(24 * time.Hour),
Note: "Note of test event 03",
NotifyTime: Dur2pbduration(1 * time.Second),
UserID: 1111,
}
func Time2pbtimestamp(t time.Time) *timestamp.Timestamp {
r, err := ptypes.TimestampProto(t)
if err != nil {