Skip to content

Commit 5b9bf7a

Browse files
authored
Merge pull request #78 from averak/release/v0.4.0
Release/v0.4.0
2 parents 5a1c408 + ad3c978 commit 5b9bf7a

File tree

17 files changed

+313
-10
lines changed

17 files changed

+313
-10
lines changed
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package master_data
2+
3+
import (
4+
"context"
5+
6+
"github.com/averak/hbaas/app/adapter/pbconv"
7+
"github.com/averak/hbaas/app/domain/repository"
8+
"github.com/averak/hbaas/app/infrastructure/connect/advice"
9+
"github.com/averak/hbaas/app/usecase/master_data_usecase"
10+
"github.com/averak/hbaas/protobuf/api"
11+
"github.com/averak/hbaas/protobuf/api/apiconnect"
12+
)
13+
14+
type handler struct {
15+
uc *master_data_usecase.Usecase
16+
}
17+
18+
func NewHandler(uc *master_data_usecase.Usecase, advice advice.Advice) apiconnect.MasterDataServiceHandler {
19+
return api.NewMasterDataServiceHandler(&handler{uc: uc}, advice)
20+
}
21+
22+
func (h handler) GetV1(ctx context.Context, _ *advice.Request[*api.MasterDataServiceGetV1Request]) (*api.MasterDataServiceGetV1Response, error) {
23+
result, err := h.uc.Get(ctx)
24+
if err != nil {
25+
return nil, err
26+
}
27+
return &api.MasterDataServiceGetV1Response{
28+
MasterData: pbconv.ToMasterDataPb(result),
29+
}, nil
30+
}
31+
32+
func (h handler) GetV1Errors(errs *api.MasterDataServiceGetV1Errors) {
33+
errs.Map(repository.ErrActiveMasterDataNotFound, errs.RESOURCE_NOT_FOUND)
34+
}
35+
36+
func (h handler) GetRevisionV1(ctx context.Context, req *advice.Request[*api.MasterDataServiceGetRevisionV1Request]) (*api.MasterDataServiceGetRevisionV1Response, error) {
37+
//TODO implement me
38+
panic("implement me")
39+
}
40+
41+
func (h handler) GetRevisionV1Errors(errs *api.MasterDataServiceGetRevisionV1Errors) {
42+
errs.Map(repository.ErrActiveMasterDataNotFound, errs.RESOURCE_NOT_FOUND)
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package master_data_test
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
"time"
9+
10+
"connectrpc.com/connect"
11+
"github.com/averak/hbaas/app/registry"
12+
"github.com/averak/hbaas/protobuf/api"
13+
"github.com/averak/hbaas/protobuf/api/api_errors"
14+
"github.com/averak/hbaas/protobuf/api/apiconnect"
15+
"github.com/averak/hbaas/protobuf/resource"
16+
"github.com/averak/hbaas/testutils"
17+
"github.com/averak/hbaas/testutils/bdd"
18+
"github.com/averak/hbaas/testutils/fixture/builder/system_builder"
19+
"github.com/averak/hbaas/testutils/fixture/setupper/systemup"
20+
"github.com/averak/hbaas/testutils/testconnect"
21+
"github.com/google/uuid"
22+
"github.com/stretchr/testify/assert"
23+
"github.com/stretchr/testify/require"
24+
"google.golang.org/protobuf/types/known/timestamppb"
25+
)
26+
27+
func Test_handler_GetV1(t *testing.T) {
28+
mux, err := registry.InitializeAPIServerMux(context.Background())
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
server := httptest.NewServer(mux)
33+
defer server.Close()
34+
35+
now := time.Now().Truncate(time.Millisecond)
36+
37+
type given struct {
38+
systemData system_builder.Data
39+
}
40+
type when struct {
41+
req *api.MasterDataServiceGetV1Request
42+
}
43+
type then = func(*testing.T, *connect.Response[api.MasterDataServiceGetV1Response], error)
44+
tests := []bdd.Testcase[given, when, then]{
45+
{
46+
Name: "有効なリビジョンが存在する状態で",
47+
Given: given{
48+
systemData: system_builder.New().
49+
MasterData(
50+
system_builder.NewMasterDataBuilder(1).
51+
Content([]byte("v1")).
52+
IsActive(true).
53+
Comment("c1").
54+
CreatedAt(now.Add(-1 * time.Hour)).
55+
Build(),
56+
).
57+
MasterData(
58+
system_builder.NewMasterDataBuilder(2).
59+
Content([]byte("v2")).
60+
IsActive(false).
61+
Comment("c2").
62+
CreatedAt(now).
63+
Build(),
64+
).
65+
Build(),
66+
},
67+
Behaviors: []bdd.Behavior[when, then]{
68+
{
69+
Name: "有効なリビジョンのマスターデータを取得できる",
70+
When: when{
71+
req: &api.MasterDataServiceGetV1Request{},
72+
},
73+
Then: func(t *testing.T, got *connect.Response[api.MasterDataServiceGetV1Response], err error) {
74+
require.NoError(t, err)
75+
76+
// 最新のリビジョンではなく、有効なリビジョンが取得される。
77+
want := &api.MasterDataServiceGetV1Response{
78+
MasterData: &resource.MasterData{
79+
Revision: 1,
80+
Content: []byte("v1"),
81+
IsActive: true,
82+
Comment: "c1",
83+
CreatedAt: timestamppb.New(now.Add(-1 * time.Hour)),
84+
},
85+
}
86+
assert.EqualExportedValues(t, want, got.Msg)
87+
},
88+
},
89+
},
90+
},
91+
{
92+
Name: "有効なリビジョンが存在しない状態で",
93+
Given: given{
94+
systemData: system_builder.New().
95+
MasterData(system_builder.NewMasterDataBuilder(1).IsActive(false).Build()).
96+
Build(),
97+
},
98+
Behaviors: []bdd.Behavior[when, then]{
99+
{
100+
Name: "エラーを返す",
101+
When: when{
102+
req: &api.MasterDataServiceGetV1Request{},
103+
},
104+
Then: func(t *testing.T, got *connect.Response[api.MasterDataServiceGetV1Response], err error) {
105+
testconnect.AssertErrorCode(t, api_errors.ErrorCode_METHOD_RESOURCE_NOT_FOUND, err)
106+
},
107+
},
108+
},
109+
},
110+
}
111+
for _, tt := range tests {
112+
tt.Run(t, func(t *testing.T, given given, when when, then then) {
113+
systemup.Setup(t, context.Background(), given.systemData)
114+
defer testutils.Teardown(t)
115+
116+
got, err := testconnect.MethodInvoke(
117+
apiconnect.NewMasterDataServiceClient(http.DefaultClient, server.URL).GetV1,
118+
when.req,
119+
testconnect.WithSpoofingUserID(uuid.New()),
120+
)
121+
then(t, got, err)
122+
})
123+
}
124+
}

app/adapter/handler/provider.go

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/averak/hbaas/app/adapter/handler/debug/echo"
88
"github.com/averak/hbaas/app/adapter/handler/global_kvs"
99
"github.com/averak/hbaas/app/adapter/handler/leader_board"
10+
"github.com/averak/hbaas/app/adapter/handler/master_data"
1011
"github.com/averak/hbaas/app/adapter/handler/private_kvs"
1112
"github.com/averak/hbaas/app/adapter/handler/session"
1213
"github.com/averak/hbaas/app/adapter/handler/user"
@@ -20,6 +21,7 @@ import (
2021
var SuperSet = wire.NewSet(
2122
global_kvs.NewHandler,
2223
leader_board.NewHandler,
24+
master_data.NewHandler,
2325
private_kvs.NewHandler,
2426
session.NewHandler,
2527
user.NewHandler,
@@ -30,6 +32,7 @@ var SuperSet = wire.NewSet(
3032
func New(
3133
globalKVS apiconnect.GlobalKVSServiceHandler,
3234
leaderBoard apiconnect.LeaderBoardServiceHandler,
35+
masterData apiconnect.MasterDataServiceHandler,
3336
privateKVS apiconnect.PrivateKVSServiceHandler,
3437
session apiconnect.SessionServiceHandler,
3538
user apiconnect.UserServiceHandler,
@@ -39,6 +42,7 @@ func New(
3942
mux := http.NewServeMux()
4043
mux.Handle(apiconnect.NewGlobalKVSServiceHandler(globalKVS, opts))
4144
mux.Handle(apiconnect.NewLeaderBoardServiceHandler(leaderBoard, opts))
45+
mux.Handle(apiconnect.NewMasterDataServiceHandler(masterData, opts))
4246
mux.Handle(apiconnect.NewPrivateKVSServiceHandler(privateKVS, opts))
4347
mux.Handle(apiconnect.NewSessionServiceHandler(session, opts))
4448
mux.Handle(apiconnect.NewUserServiceHandler(user, opts))

app/adapter/pbconv/master_data.go

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package pbconv
2+
3+
import (
4+
"github.com/averak/hbaas/app/domain/model"
5+
"github.com/averak/hbaas/protobuf/resource"
6+
"google.golang.org/protobuf/types/known/timestamppb"
7+
)
8+
9+
func ToMasterDataPb(m model.MasterData) *resource.MasterData {
10+
return &resource.MasterData{
11+
Revision: int64(m.Revision),
12+
Content: m.Content,
13+
IsActive: m.IsActive,
14+
Comment: m.Comment,
15+
CreatedAt: timestamppb.New(m.CreatedAt),
16+
}
17+
}

app/adapter/repoimpl/master_data_repoimpl/repository.go

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ func (r Repository) Get(ctx context.Context, tx transaction.Transaction, revisio
2626
ctx, span := trace.StartSpan(ctx, "master_data_repoimpl.Get")
2727
defer span.End()
2828

29+
// TODO: マスターデータをキャッシュする。なお、複数世代キャッシュする必要はない。
30+
2931
dto, err := dao.FindMasterDatum(ctx, tx, revision)
3032
if err != nil {
3133
if errors.Is(err, sql.ErrNoRows) {

app/registry/wire_gen.go

+7-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package master_data_usecase
2+
3+
import (
4+
"context"
5+
6+
"github.com/averak/hbaas/app/domain/model"
7+
"github.com/averak/hbaas/app/domain/repository/transaction"
8+
)
9+
10+
func (u Usecase) Get(ctx context.Context) (model.MasterData, error) {
11+
var res model.MasterData
12+
err := u.conn.BeginRoTransaction(ctx, func(ctx context.Context, tx transaction.Transaction) error {
13+
var err error
14+
res, err = u.masterDataRepo.GetActive(ctx, tx)
15+
if err != nil {
16+
return err
17+
}
18+
return nil
19+
})
20+
if err != nil {
21+
return model.MasterData{}, err
22+
}
23+
return res, nil
24+
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package master_data_usecase
2+
3+
import (
4+
"github.com/averak/hbaas/app/domain/repository"
5+
"github.com/averak/hbaas/app/domain/repository/transaction"
6+
)
7+
8+
type Usecase struct {
9+
conn transaction.Connection
10+
masterDataRepo repository.MasterDataRepository
11+
}
12+
13+
func NewUsecase(conn transaction.Connection, masterDataRepo repository.MasterDataRepository) *Usecase {
14+
return &Usecase{
15+
conn: conn,
16+
masterDataRepo: masterDataRepo,
17+
}
18+
}

app/usecase/provider.go

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/averak/hbaas/app/usecase/echo_usecase"
55
"github.com/averak/hbaas/app/usecase/global_kvs_usecase"
66
"github.com/averak/hbaas/app/usecase/leader_board_usecase"
7+
"github.com/averak/hbaas/app/usecase/master_data_usecase"
78
"github.com/averak/hbaas/app/usecase/private_kvs_usecase"
89
"github.com/averak/hbaas/app/usecase/session_usecase"
910
"github.com/averak/hbaas/app/usecase/user_usecase"
@@ -14,6 +15,7 @@ var SuperSet = wire.NewSet(
1415
session_usecase.NewUsecase,
1516
global_kvs_usecase.NewUsecase,
1617
leader_board_usecase.NewUsecase,
18+
master_data_usecase.NewUsecase,
1719
private_kvs_usecase.NewUsecase,
1820
echo_usecase.NewUsecase,
1921
user_usecase.NewUsecase,

docker/api-server/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.22 AS builder
1+
FROM golang:1.23 AS builder
22

33
WORKDIR /app
44

docker/async-worker/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.22 AS builder
1+
FROM golang:1.23 AS builder
22

33
WORKDIR /app
44

docker/batch-job/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.22 AS builder
1+
FROM golang:1.23 AS builder
22

33
WORKDIR /app
44

docker/db-migrate/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.22 AS builder
1+
FROM golang:1.23 AS builder
22

33
ENV POSTGRES_USER=db
44
ENV POSTGRES_PASSWORD=db

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/averak/hbaas
22

3-
go 1.22
3+
go 1.23
44

55
require (
66
cloud.google.com/go/pubsub v1.40.0
@@ -29,6 +29,7 @@ require (
2929
golang.org/x/net v0.27.0
3030
google.golang.org/api v0.188.0
3131
google.golang.org/genproto/googleapis/rpc v0.0.0-20240709173604-40e1e62336c5
32+
google.golang.org/grpc v1.64.1
3233
google.golang.org/protobuf v1.34.2
3334
)
3435

@@ -75,6 +76,5 @@ require (
7576
google.golang.org/appengine/v2 v2.0.2 // indirect
7677
google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b // indirect
7778
google.golang.org/genproto/googleapis/api v0.0.0-20240709173604-40e1e62336c5 // indirect
78-
google.golang.org/grpc v1.64.1 // indirect
7979
gopkg.in/yaml.v3 v3.0.1 // indirect
8080
)

0 commit comments

Comments
 (0)