Initial commit
This commit is contained in:
147
backend/service/note_service.go
Normal file
147
backend/service/note_service.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
notesv1 "backend/gen/notes/v1"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
// NoteService — реализация gRPC сервиса, сгенерированного из proto.
|
||||
// Типы notesv1.Note, notesv1.CreateNoteRequest и т.д. —
|
||||
// это всё автоматически сгенерированные из proto файла структуры.
|
||||
// Если ты изменишь proto (добавишь поле, переименуешь) и
|
||||
// перегенерируешь — этот код перестанет компилироваться,
|
||||
// пока ты не обновишь реализацию. Вот в чём магия.
|
||||
type NoteService struct {
|
||||
notesv1.UnimplementedNoteServiceServer
|
||||
mu sync.RWMutex
|
||||
notes map[string]*notesv1.Note
|
||||
}
|
||||
|
||||
func NewNoteService() *NoteService {
|
||||
return &NoteService{
|
||||
notes: make(map[string]*notesv1.Note),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *NoteService) CreateNote(
|
||||
ctx context.Context,
|
||||
req *notesv1.CreateNoteRequest,
|
||||
) (*notesv1.Note, error) {
|
||||
if req.Title == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "title is required")
|
||||
}
|
||||
|
||||
now := timestamppb.New(time.Now())
|
||||
note := ¬esv1.Note{
|
||||
Id: uuid.New().String(),
|
||||
Title: req.Title,
|
||||
Content: req.Content,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
s.notes[note.Id] = note
|
||||
s.mu.Unlock()
|
||||
|
||||
return note, nil
|
||||
}
|
||||
|
||||
func (s *NoteService) GetNote(
|
||||
ctx context.Context,
|
||||
req *notesv1.GetNoteRequest,
|
||||
) (*notesv1.Note, error) {
|
||||
s.mu.RLock()
|
||||
note, ok := s.notes[req.Id]
|
||||
s.mu.RUnlock()
|
||||
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.NotFound, "note %s not found", req.Id)
|
||||
}
|
||||
return note, nil
|
||||
}
|
||||
|
||||
func (s *NoteService) UpdateNote(
|
||||
ctx context.Context,
|
||||
req *notesv1.UpdateNoteRequest,
|
||||
) (*notesv1.Note, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
note, ok := s.notes[req.Id]
|
||||
if !ok {
|
||||
return nil, status.Errorf(codes.NotFound, "note %s not found", req.Id)
|
||||
}
|
||||
|
||||
note.Title = req.Title
|
||||
note.Content = req.Content
|
||||
note.UpdatedAt = timestamppb.New(time.Now())
|
||||
|
||||
return note, nil
|
||||
}
|
||||
|
||||
func (s *NoteService) DeleteNote(
|
||||
ctx context.Context,
|
||||
req *notesv1.DeleteNoteRequest,
|
||||
) (*emptypb.Empty, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if _, ok := s.notes[req.Id]; !ok {
|
||||
return nil, status.Errorf(codes.NotFound, "note %s not found", req.Id)
|
||||
}
|
||||
|
||||
delete(s.notes, req.Id)
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *NoteService) ListNotes(
|
||||
ctx context.Context,
|
||||
req *notesv1.ListNotesRequest,
|
||||
) (*notesv1.ListNotesResponse, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
all := make([]*notesv1.Note, 0, len(s.notes))
|
||||
for _, n := range s.notes {
|
||||
all = append(all, n)
|
||||
}
|
||||
|
||||
// Простая пагинация
|
||||
total := int32(len(all))
|
||||
pageSize := req.PageSize
|
||||
if pageSize <= 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
page := req.Page
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
start := (page - 1) * pageSize
|
||||
if start >= total {
|
||||
return ¬esv1.ListNotesResponse{
|
||||
Notes: []*notesv1.Note{},
|
||||
TotalCount: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
end := start + pageSize
|
||||
if end > total {
|
||||
end = total
|
||||
}
|
||||
|
||||
return ¬esv1.ListNotesResponse{
|
||||
Notes: all[start:end],
|
||||
TotalCount: total,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user