[hw-8] attempt to fix tests

This commit is contained in:
3ybacTuK
2025-07-28 22:11:42 +03:00
parent 6e0d90a6d5
commit 61757d1a52
8 changed files with 676 additions and 66 deletions

View File

@@ -27,10 +27,12 @@ db-create-migration:
$(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) create -s $(n) sql $(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) create -s $(n) sql
db-migrate: db-migrate:
$(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "$(LOCAL_DB_DSN)" up $(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "postgresql://$(PROD_USER)-1:$(PROD_PASS)-1@192.168.64.5:5438/comments_db?sslmode=disable" up
$(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "postgresql://$(PROD_USER)-2:$(PROD_PASS)-2@192.168.64.5:5439/comments_db?sslmode=disable" up
db-migrate-down: db-migrate-down:
$(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "$(LOCAL_DB_DSN)" down $(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "postgresql://$(PROD_USER)-1:$(PROD_PASS)-1@192.168.64.5:5438/comments_db?sslmode=disable" down
$(BINDIR)/goose -dir $(MIGRATIONS_FOLDER) postgres "postgresql://$(PROD_USER)-2:$(PROD_PASS)-2@192.168.64.5:5439/comments_db?sslmode=disable" down
db-reset-local: db-reset-local:
psql -c "drop database if exists \"$(LOCAL_DB_NAME)\"" psql -c "drop database if exists \"$(LOCAL_DB_NAME)\""

View File

@@ -7,14 +7,14 @@ service:
http_port: 8086 http_port: 8086
db_shards: db_shards:
- host: localhost - host: 192.168.64.5
port: 5434 port: 5438
user: comments-user-1 user: comments-user-1
password: comments-password-1 password: comments-password-1
db_name: comments_db db_name: comments_db
- host: localhost - host: 192.168.64.5
port: 5435 port: 5439
user: comments-user-2 user: comments-user-2
password: comments-password-2 password: comments-password-2
db_name: comments_db db_name: comments_db

View File

@@ -1,6 +1,6 @@
-- +goose Up -- +goose Up
CREATE TABLE comments ( CREATE TABLE comments (
id BIGSERIAL PRIMARY KEY, id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL, user_id BIGINT NOT NULL,
sku BIGINT NOT NULL, sku BIGINT NOT NULL,
text VARCHAR(255) NOT NULL, text VARCHAR(255) NOT NULL,
@@ -12,5 +12,3 @@ CREATE INDEX user_id_idx ON comments(user_id, created_at DESC);
-- +goose Down -- +goose Down
DROP TABLE comments; DROP TABLE comments;
DROP INDEX sku_idx;
DROP INDEX user_id_idx;

View File

@@ -1,5 +1,5 @@
-- name: InsertComment :one -- name: InsertComment :one
INSERT INTO comments (user_id, sku, text) VALUES ($1, $2, $3) INSERT INTO comments (id, user_id, sku, text) VALUES ($1, $2, $3, $4)
RETURNING id, user_id, sku, text, created_at; RETURNING id, user_id, sku, text, created_at;
-- name: GetCommentByID :one -- name: GetCommentByID :one

View File

@@ -27,18 +27,24 @@ func (q *Queries) GetCommentByID(ctx context.Context, id int64) (*Comment, error
} }
const insertComment = `-- name: InsertComment :one const insertComment = `-- name: InsertComment :one
INSERT INTO comments (user_id, sku, text) VALUES ($1, $2, $3) INSERT INTO comments (id, user_id, sku, text) VALUES ($1, $2, $3, $4)
RETURNING id, user_id, sku, text, created_at RETURNING id, user_id, sku, text, created_at
` `
type InsertCommentParams struct { type InsertCommentParams struct {
ID int64
UserID int64 UserID int64
Sku int64 Sku int64
Text string Text string
} }
func (q *Queries) InsertComment(ctx context.Context, arg *InsertCommentParams) (*Comment, error) { func (q *Queries) InsertComment(ctx context.Context, arg *InsertCommentParams) (*Comment, error) {
row := q.db.QueryRow(ctx, insertComment, arg.UserID, arg.Sku, arg.Text) row := q.db.QueryRow(ctx, insertComment,
arg.ID,
arg.UserID,
arg.Sku,
arg.Text,
)
var i Comment var i Comment
err := row.Scan( err := row.Scan(
&i.ID, &i.ID,

View File

@@ -3,6 +3,7 @@ package sqlc
import ( import (
"context" "context"
"errors" "errors"
"sync"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool" "github.com/jackc/pgx/v5/pgxpool"
@@ -15,21 +16,25 @@ import (
type commentsRepo struct { type commentsRepo struct {
shard1 *pgxpool.Pool shard1 *pgxpool.Pool
shard2 *pgxpool.Pool shard2 *pgxpool.Pool
curID int64
idMx sync.Mutex
} }
func NewCommentsRepository(shard1, shard2 *pgxpool.Pool) *commentsRepo { func NewCommentsRepository(shard1, shard2 *pgxpool.Pool) *commentsRepo {
return &commentsRepo{ return &commentsRepo{
shard1: shard1, shard1: shard1,
shard2: shard2, shard2: shard2,
curID: 1,
} }
} }
func (r *commentsRepo) pickShard(sku int64) *pgxpool.Pool { func (r *commentsRepo) pickShard(sku int64) (*pgxpool.Pool, int64) {
if sku%2 == 0 { if sku%2 == 0 {
return r.shard1 return r.shard1, 0
} }
return r.shard2 return r.shard2, 1
} }
func mapComment(c *Comment) *entity.Comment { func mapComment(c *Comment) *entity.Comment {
@@ -67,13 +72,19 @@ func (r *commentsRepo) GetCommentByID(ctx context.Context, id int64) (*entity.Co
} }
func (r *commentsRepo) InsertComment(ctx context.Context, comment *entity.Comment) (*entity.Comment, error) { func (r *commentsRepo) InsertComment(ctx context.Context, comment *entity.Comment) (*entity.Comment, error) {
shard := r.pickShard(comment.SKU) shard, shardID := r.pickShard(comment.SKU)
q := New(shard) q := New(shard)
r.idMx.Lock()
id := r.curID*1000 + shardID
r.curID++
r.idMx.Unlock()
req := &InsertCommentParams{ req := &InsertCommentParams{
UserID: comment.UserID, UserID: comment.UserID,
Sku: comment.SKU, Sku: comment.SKU,
Text: comment.Text, Text: comment.Text,
ID: id,
} }
c, err := q.InsertComment(ctx, req) c, err := q.InsertComment(ctx, req)
@@ -85,7 +96,7 @@ func (r *commentsRepo) InsertComment(ctx context.Context, comment *entity.Commen
} }
func (r *commentsRepo) ListCommentsBySku(ctx context.Context, sku int64) ([]*entity.Comment, error) { func (r *commentsRepo) ListCommentsBySku(ctx context.Context, sku int64) ([]*entity.Comment, error) {
shard := r.pickShard(sku) shard, _ := r.pickShard(sku)
q := New(shard) q := New(shard)
list, err := q.ListCommentsBySku(ctx, sku) list, err := q.ListCommentsBySku(ctx, sku)

View File

@@ -5,57 +5,57 @@ volumes:
shard2-data: {} shard2-data: {}
services: services:
cart: # cart:
build: # build:
context: . # context: .
dockerfile: cart/Dockerfile # dockerfile: cart/Dockerfile
ports: # ports:
- "8080:8080" # - "8080:8080"
depends_on: # depends_on:
- product-service # - product-service
product-service: # product-service:
image: gitlab-registry.ozon.dev/go/classroom-18/students/homework-draft/products:latest # image: gitlab-registry.ozon.dev/go/classroom-18/students/homework-draft/products:latest
ports: # ports:
- "8082:8082" # - "8082:8082"
loms: # loms:
build: # build:
context: . # context: .
dockerfile: loms/Dockerfile # dockerfile: loms/Dockerfile
depends_on: # depends_on:
postgres-master: # postgres-master:
condition: service_started # condition: service_started
init-kafka: # init-kafka:
condition: service_completed_successfully # condition: service_completed_successfully
ports: # ports:
- "8083:8083" # - "8083:8083"
- "8084:8084" # - "8084:8084"
- "8085:8085" # - "8085:8085"
notifier: # notifier:
build: # build:
context: . # context: .
dockerfile: notifier/Dockerfile # dockerfile: notifier/Dockerfile
depends_on: # depends_on:
init-kafka: # init-kafka:
condition: service_completed_successfully # condition: service_completed_successfully
deploy: # deploy:
replicas: 3 # replicas: 3
comments: # comments:
build: # build:
context: . # context: .
dockerfile: comments/Dockerfile # dockerfile: comments/Dockerfile
depends_on: # depends_on:
postgres-comments-shard-1: # postgres-comments-shard-1:
condition: service_started # condition: service_started
postgres-comments-shard-2: # postgres-comments-shard-2:
condition: service_started # condition: service_started
ports: # ports:
- "8083:8083" # - "8083:8083"
- "8084:8084" # - "8084:8084"
- "8085:8085" # - "8085:8085"
postgres-master: postgres-master:
image: gitlab-registry.ozon.dev/go/classroom-18/students/base/postgres:16 image: gitlab-registry.ozon.dev/go/classroom-18/students/base/postgres:16
@@ -98,7 +98,7 @@ services:
POSTGRES_USER: comments-user-1 POSTGRES_USER: comments-user-1
POSTGRES_PASSWORD: comments-password-1 POSTGRES_PASSWORD: comments-password-1
ports: ports:
- "5432:5432" - "5438:5432"
volumes: volumes:
- shard1-data:/var/lib/postgresql/data - shard1-data:/var/lib/postgresql/data
@@ -109,7 +109,7 @@ services:
POSTGRES_USER: comments-user-2 POSTGRES_USER: comments-user-2
POSTGRES_PASSWORD: comments-password-2 POSTGRES_PASSWORD: comments-password-2
ports: ports:
- "5432:5432" - "5439:5432"
volumes: volumes:
- shard2-data:/var/lib/postgresql/data - shard2-data:/var/lib/postgresql/data

View File

@@ -0,0 +1,593 @@
########################## add
### add valid comment
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": 42,
"sku": 1004005,
"comment": "hello world"
}
### Expect:
### {
### "id": "1001"
### }
### add invalid comment, miss user_id
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"sku": 1004005,
"comment": "hello world"
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentAddRequest.UserId: value must be greater than 0",
### "details": []
### }
### add invalid comment, negative user_id
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": -42,
"sku": 1004005,
"comment": "hello world"
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentAddRequest.UserId: value must be greater than 0",
### "details": []
### }
### add invalid comment, miss sku
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": 42,
"comment": "hello world"
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentAddRequest.Sku: value must be greater than 0",
### "details": []
### }
### add invalid comment, negative sku
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": 42,
"sku": -10,
"comment": "hello world"
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentAddRequest.Sku: value must be greater than 0",
### "details": []
### }
### add invalid comment, miss comment
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": 42,
"sku": 1004005
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentAddRequest.Comment: value length must be between 1 and 255 runes, inclusive",
### "details": []
### }
### add invalid comment, empty comment
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": 42,
"sku": 1004005,
"comment": ""
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentAddRequest.Comment: value length must be between 1 and 255 runes, inclusive",
### "details": []
### }
### add invalid comment, too large comment
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": 42,
"sku": 1004005,
"comment": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456"
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentAddRequest.Comment: value length must be between 1 and 255 runes, inclusive",
### "details": []
### }
########################## get by id
### set precondition BEGIN ###
### save comment_id from response
### add valid comment
POST http://localhost:8086/comment/add
Content-Type: application/json
{
"user_id": 123,
"sku": 456005,
"comment": "hello world 123"
}
### Expect:
### {
### "id": "8000"
### }
### set precondition END ###
### get valid, previously created, comment
POST http://localhost:8086/comment/get-by-id
Content-Type: application/json
{
"id": 8000
}
### Expect:
### {
### "id": "8000",
### "user_id": "123",
### "sku": "456005",
### "comment": "hello world 123",
### "created_at": "2025-01-13T17:15:17.252417Z"
### }
### get comment by invalid id (negative)
POST http://localhost:8086/comment/get-by-id
Content-Type: application/json
{
"id": -8000
}
### Expect:
### {
### "code": 3,
### "message": "invalid CommentGetByIDRequest.Id: value must be greater than 0",
### "details": []
### }
### get comment by id, which not exists
POST http://localhost:8086/comment/get-by-id
Content-Type: application/json
{
"id": 404000
}
### Expect:
### {
### "code": 5,
### "message": "comment with id=404000 not found",
### "details": []
### }
########################## edit
### edit valid comment
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"comment_id": 1001,
"new_comment": "hello world changed"
}
### Expect
### {}
### edit invalid comment, user is not an author
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 555555,
"comment_id": 1001,
"new_comment": "hello world changed"
}
### Expect
### {
### "code": 7,
### "message": "unable to edit comment: given user is not an author of modified comment",
### "details": []
### }
### edit invalid comment, comment is not exists
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"comment_id": 555551001,
"new_comment": "hello world changed"
}
### Expect
### {
### "code": 5,
### "message": "editing comment is not found",
### "details": []
### }
### edit invalid comment, miss user_id
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"comment_id": 1001,
"new_comment": "hello world changed"
}
### Expect
### {
### "code": 3,
### "message": "invalid CommentEditRequest.UserId: value must be greater than 0",
### "details": []
### }
### edit invalid comment, negative user_id
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": -42,
"comment_id": 1001,
"new_comment": "hello world changed"
}
### Expect
### {
### "code": 3,
### "message": "invalid CommentEditRequest.UserId: value must be greater than 0",
### "details": []
### }
### edit invalid comment, miss comment_id
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"new_comment": "hello world changed"
}
### Expect
### {
### "code": 3,
### "message": "invalid CommentEditRequest.CommentId: value must be greater than 0",
### "details": []
### }
### edit invalid comment, negative comment_id
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"comment_id": -1001,
"new_comment": "hello world changed"
}
### Expect
### {
### "code": 3,
### "message": "invalid CommentEditRequest.CommentId: value must be greater than 0",
### "details": []
### }
### edit invalid comment, miss new_comment
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"comment_id": 1001
}
### Expect
### {
### "code": 3,
### "message": "invalid CommentEditRequest.NewComment: value length must be between 1 and 255 runes, inclusive",
### "details": []
### }
### edit invalid comment, empty new_comment
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"comment_id": 1001,
"new_comment": ""
}
### Expect
### {
### "code": 3,
### "message": "invalid CommentEditRequest.NewComment: value length must be between 1 and 255 runes, inclusive",
### "details": []
### }
### edit invalid comment, too long new_comment
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"comment_id": 1001,
"new_comment": "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456"
}
### Expect
### {
### "code": 3,
### "message": "invalid CommentEditRequest.NewComment: value length must be between 1 and 255 runes, inclusive",
### "details": []
### }
### edit valid comment, but editable time expired (CHANGE EditInterval!!!)
POST http://localhost:8086/comment/edit
Content-Type: application/json
{
"user_id": 42,
"comment_id": 1001,
"new_comment": "hello world changed 3"
}
### Expect
### {
### "code": 9,
### "message": "unable to edit comment: editing time interval expired",
### "details": []
### }
########################## list by sku
### set precondition BEGIN ###
### add valid comment 1
POST http://localhost:8086/comment/add
Content-Type: application/json
{"user_id": 71, "sku": 123, "comment": "hello world 1"}
### add valid comment 2
POST http://localhost:8086/comment/add
Content-Type: application/json
{"user_id": 71, "sku": 123, "comment": "hello world 2"}
### add valid comment 3
POST http://localhost:8086/comment/add
Content-Type: application/json
{"user_id": 71, "sku": 123, "comment": "hello world 3"}
### set precondition END ###
### list comments by sku
POST http://localhost:8086/comment/list-by-sku
Content-Type: application/json
{"sku": 123}
### Expected (order created_at DESC, IMPORTANT!!!):
### {
### "comments": [
### {
### "id": "5001",
### "user_id": "71",
### "comment": "hello world 3",
### "created_at": "2024-12-24T22:32:54.301507Z"
### },
### {
### "id": "4001",
### "user_id": "71",
### "comment": "hello world 2",
### "created_at": "2024-12-24T22:32:52.656693Z"
### },
### {
### "id": "3001",
### "user_id": "71",
### "comment": "hello world 1",
### "created_at": "2024-12-24T22:32:50.302224Z"
### }
### ]
### }
### list comments by sku, sku have no comments yet
POST http://localhost:8086/comment/list-by-sku
Content-Type: application/json
{"sku": 444444}
### Expected:
### {
### "comments": []
### }
### list comments by sku, invalid, miss sku
POST http://localhost:8086/comment/list-by-sku
Content-Type: application/json
{}
### Expected:
### {
### "code": 3,
### "message": "invalid CommentListBySKURequest.Sku: value must be greater than 0",
### "details": []
### }
### list comments by sku, invalid, negative sku
POST http://localhost:8086/comment/list-by-sku
Content-Type: application/json
{
"sku": -1234
}
### Expected:
### {
### "code": 3,
### "message": "invalid CommentListBySKURequest.Sku: value must be greater than 0",
### "details": []
### }
########################## list by user
### set precondition BEGIN ###
### add valid comment 1
POST http://localhost:8086/comment/add
Content-Type: application/json
{"user_id": 54, "sku": 789, "comment": "comment #1 54-789 (shard-2)"}
### add valid comment 1
POST http://localhost:8086/comment/add
Content-Type: application/json
{"user_id": 54, "sku": 456, "comment": "comment #1 54-456 (shard-1)"}
### add valid comment 2
POST http://localhost:8086/comment/add
Content-Type: application/json
{"user_id": 54, "sku": 220, "comment": "comment #2 54-220 (shard-1)"}
### add valid comment 3
POST http://localhost:8086/comment/add
Content-Type: application/json
{"user_id": 54, "sku": 567, "comment": "comment #2 54-567 (shard-2)"}
### set precondition END ###
### list comments by user
POST http://localhost:8086/comment/list-by-user
Content-Type: application/json
{"user_id": 54}
### Expected (order by created_at DESC, IMPORTANT!!!):
### {
### "comments": [
### {
### "id": "13001",
### "sku": "567",
### "comment": "comment #2 54-567 (shard-2)",
### "created_at": "2024-12-24T22:45:52.284861Z"
### },
### {
### "id": "5000",
### "sku": "220",
### "comment": "comment #2 54-220 (shard-1)",
### "created_at": "2024-12-24T22:45:49.050342Z"
### },
### {
### "id": "4000",
### "sku": "456",
### "comment": "comment #1 54-456 (shard-1)",
### "created_at": "2024-12-24T22:45:45.511675Z"
### },
### {
### "id": "12001",
### "sku": "789",
### "comment": "comment #1 54-789 (shard-2)",
### "created_at": "2024-12-24T22:45:39.449233Z"
### }
### ]
### }
### list comments by user, no comments for user
POST http://localhost:8086/comment/list-by-user
Content-Type: application/json
{"user_id": 32423423}
### Expected:
### {
### "comments": []
### }