Skip to content
This repository was archived by the owner on Dec 6, 2025. It is now read-only.

Commit a5a9b45

Browse files
committed
room
1 parent 831480f commit a5a9b45

File tree

5 files changed

+135
-12
lines changed

5 files changed

+135
-12
lines changed

services/tasks-svc/internal/room/room.go

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package room
22

33
import (
4+
"common"
45
"context"
6+
commonpb "gen/libs/common/v1"
57
"github.com/google/uuid"
68
"google.golang.org/grpc/codes"
79
"google.golang.org/grpc/status"
10+
"google.golang.org/protobuf/types/known/wrapperspb"
811
"hwdb"
912
"hwutil"
1013
"strconv"
1114
"tasks-svc/internal/tracking"
15+
"tasks-svc/internal/util"
1216
"tasks-svc/repos/room_repo"
1317

1418
pb "gen/services/tasks_svc/v1"
@@ -100,7 +104,6 @@ func (ServiceServer) GetRoom(ctx context.Context, req *pb.GetRoomRequest) (*pb.G
100104
}
101105

102106
func (ServiceServer) UpdateRoom(ctx context.Context, req *pb.UpdateRoomRequest) (*pb.UpdateRoomResponse, error) {
103-
roomRepo := room_repo.New(hwdb.GetDB())
104107

105108
// TODO: Auth
106109

@@ -109,7 +112,20 @@ func (ServiceServer) UpdateRoom(ctx context.Context, req *pb.UpdateRoomRequest)
109112
return nil, status.Error(codes.InvalidArgument, err.Error())
110113
}
111114

112-
consistency, err := roomRepo.UpdateRoom(ctx, room_repo.UpdateRoomParams{
115+
expConsistency, ok := hwutil.ParseConsistency(req.Consistency)
116+
if !ok {
117+
return nil, common.UnparsableConsistencyError(ctx, "consistency")
118+
}
119+
120+
// Start TX
121+
tx, rollback, err := hwdb.BeginTx(hwdb.GetDB(), ctx)
122+
if err != nil {
123+
return nil, err
124+
}
125+
defer rollback()
126+
roomRepo := room_repo.New(tx)
127+
128+
result, err := roomRepo.UpdateRoom(ctx, room_repo.UpdateRoomParams{
113129
ID: patientID,
114130
Name: req.Name,
115131
})
@@ -118,9 +134,42 @@ func (ServiceServer) UpdateRoom(ctx context.Context, req *pb.UpdateRoomRequest)
118134
return nil, err
119135
}
120136

137+
// conflict detection
138+
if expConsistency != nil && *expConsistency != uint64(result.OldConsistency) {
139+
conflicts := make(map[string]*commonpb.AttributeConflict)
140+
141+
if req.Name != nil && *req.Name != result.OldName {
142+
conflicts["name"], err = util.AttributeConflict(
143+
wrapperspb.String(result.OldName),
144+
wrapperspb.String(*req.Name),
145+
)
146+
if err != nil {
147+
return nil, err
148+
}
149+
}
150+
151+
if len(conflicts) != 0 {
152+
// prevent the update
153+
if err := hwdb.Error(ctx, tx.Rollback(ctx)); err != nil {
154+
return nil, err
155+
}
156+
157+
// return conflict
158+
return &pb.UpdateRoomResponse{
159+
Conflict: &commonpb.Conflict{ConflictingAttributes: conflicts},
160+
Consistency: strconv.FormatUint(uint64(result.OldConsistency), 10),
161+
}, nil
162+
}
163+
}
164+
165+
// Commit Update
166+
if err := hwdb.Error(ctx, tx.Commit(ctx)); err != nil {
167+
return nil, err
168+
}
169+
121170
return &pb.UpdateRoomResponse{
122-
Conflict: nil, // TODO
123-
Consistency: strconv.FormatUint(uint64(consistency), 10),
171+
Conflict: nil,
172+
Consistency: strconv.FormatUint(uint64(result.Consistency), 10),
124173
}, nil
125174
}
126175

services/tasks-svc/repos/room_repo.sql

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,21 @@ WHERE rooms.ward_id = @ward_id
7676
ORDER BY rooms.id ASC, beds.name ASC;
7777

7878
-- name: UpdateRoom :one
79+
WITH old_table AS (
80+
SELECT
81+
name as old_name,
82+
consistency as old_consistency
83+
FROM rooms
84+
WHERE rooms.id = @id
85+
)
7986
UPDATE rooms
8087
SET name = coalesce(sqlc.narg('name'), name),
8188
consistency = consistency + 1
82-
WHERE id = @id
83-
RETURNING consistency;
89+
WHERE rooms.id = @id
90+
RETURNING
91+
consistency,
92+
(SELECT old_name FROM old_table),
93+
(SELECT old_consistency FROM old_table);
8494

8595
-- name: DeleteRoom :exec
8696
DELETE FROM rooms WHERE id = @id;

services/tasks-svc/repos/room_repo/room_repo.sql.go

Lines changed: 22 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/tasks-svc/stories/RoomCRUD_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
pb "gen/services/tasks_svc/v1"
77
"github.com/stretchr/testify/assert"
8+
"google.golang.org/protobuf/types/known/wrapperspb"
89
"hwutil"
910
"strconv"
1011
"testing"
@@ -287,3 +288,48 @@ func TestGetRoomOverviewsByWard(t *testing.T) {
287288
assert.JSONEq(t, string(expectedRoomAJson), string(resRoomAJson))
288289
assert.JSONEq(t, string(expectedRoomBJson), string(resRoomBJson))
289290
}
291+
292+
func TestUpdateRoomConflict(t *testing.T) {
293+
ctx := context.Background()
294+
roomClient := roomServiceClient()
295+
296+
// prepare
297+
wardId, _ := prepareWard(t, ctx, "")
298+
roomId, initialConsistency := prepareRoom(t, ctx, wardId, "")
299+
300+
name1 := "This came first"
301+
302+
// update 1
303+
update1Res, err := roomClient.UpdateRoom(ctx, &pb.UpdateRoomRequest{
304+
Id: roomId,
305+
Name: &name1,
306+
Consistency: &initialConsistency,
307+
})
308+
assert.NoError(t, err)
309+
assert.Nil(t, update1Res.Conflict)
310+
assert.NotEqual(t, initialConsistency, update1Res.Consistency)
311+
312+
name2 := "This came second"
313+
314+
// racing update 2
315+
update2Res, err := roomClient.UpdateRoom(ctx, &pb.UpdateRoomRequest{
316+
Id: roomId,
317+
Name: &name2,
318+
Consistency: &initialConsistency,
319+
})
320+
assert.NoError(t, err)
321+
assert.Equal(t, update1Res.Consistency, update2Res.Consistency)
322+
assert.NotNil(t, update2Res.Conflict)
323+
324+
nameRes := update2Res.Conflict.ConflictingAttributes["name"]
325+
assert.NotNil(t, nameRes)
326+
327+
nameIs := &wrapperspb.StringValue{}
328+
assert.NoError(t, nameRes.Is.UnmarshalTo(nameIs))
329+
assert.Equal(t, name1, nameIs.Value)
330+
331+
nameWant := &wrapperspb.StringValue{}
332+
assert.NoError(t, nameRes.Want.UnmarshalTo(nameWant))
333+
assert.Equal(t, name2, nameWant.Value)
334+
335+
}

services/tasks-svc/stories/WardCRUD_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ func TestGetRecentWards(t *testing.T) {
110110
Id: patientID,
111111
BedId: bedId,
112112
})
113+
time.Sleep(time.Millisecond * 100)
114+
113115
assert.NoError(t, err, "could not assign bed to patient")
114116
_, err = taskClient.CreateTask(ctx, &pb.CreateTaskRequest{
115117
Name: t.Name() + " Patient " + bedSuffix + " Task ",

0 commit comments

Comments
 (0)