Skip to content

Commit f41105d

Browse files
author
Jeff Yanta
committed
iap: remove prisma from postgres store
1 parent 419f35e commit f41105d

File tree

4 files changed

+127
-102
lines changed

4 files changed

+127
-102
lines changed

iap/postgres/model.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package postgres
2+
3+
import (
4+
"context"
5+
"strings"
6+
"time"
7+
8+
"github.com/georgysavva/scany/v2/pgxscan"
9+
"github.com/jackc/pgx/v5/pgxpool"
10+
11+
commonpb "github.com/code-payments/flipchat-protobuf-api/generated/go/common/v1"
12+
13+
pg "github.com/code-payments/flipchat-server/database/postgres"
14+
"github.com/code-payments/flipchat-server/iap"
15+
)
16+
17+
const (
18+
iapsTableName = "flipchat_iap"
19+
allIapFields = `"receiptId", "platform", "userId", "product", "state", "createdAt"`
20+
)
21+
22+
type model struct {
23+
ReceiptID string `db:"receiptId"`
24+
Platform int `db:"platform"`
25+
UserID string `db:"userId"`
26+
Product int `db:"product"`
27+
State int `db:"state"`
28+
CreatedAt time.Time `db:"createdAt"`
29+
}
30+
31+
func toModel(purchase *iap.Purchase) (*model, error) {
32+
return &model{
33+
ReceiptID: pg.Encode(purchase.ReceiptID),
34+
Platform: int(purchase.Platform),
35+
UserID: pg.Encode(purchase.User.Value),
36+
Product: int(purchase.Product),
37+
State: int(purchase.State),
38+
}, nil
39+
}
40+
41+
func fromModel(m *model) (*iap.Purchase, error) {
42+
decodedReceiptID, err := pg.Decode(m.ReceiptID)
43+
if err != nil {
44+
return nil, err
45+
}
46+
47+
decodedUserID, err := pg.Decode(m.UserID)
48+
if err != nil {
49+
return nil, err
50+
}
51+
52+
return &iap.Purchase{
53+
ReceiptID: decodedReceiptID,
54+
Platform: commonpb.Platform(m.Platform),
55+
User: &commonpb.UserId{Value: decodedUserID},
56+
Product: iap.Product(m.Product),
57+
State: iap.State(m.State),
58+
}, nil
59+
}
60+
61+
func (m *model) dbPut(ctx context.Context, pool *pgxpool.Pool) error {
62+
query := `INSERT INTO ` + iapsTableName + `(` + allIapFields + `) VALUES ($1, $2, $3, $4, $5, NOW()) RETURNING ` + allIapFields
63+
err := pgxscan.Get(
64+
ctx,
65+
pool,
66+
m,
67+
query,
68+
m.ReceiptID,
69+
m.Platform,
70+
m.UserID,
71+
m.Product,
72+
m.State,
73+
)
74+
if err == nil {
75+
return nil
76+
} else if strings.Contains(err.Error(), "23505") { // todo: better utility for detecting unique violations
77+
return iap.ErrExists
78+
}
79+
return err
80+
}
81+
82+
func dbGetPurchase(ctx context.Context, pool *pgxpool.Pool, receiptID []byte) (*model, error) {
83+
res := &model{}
84+
query := `SELECT ` + allIapFields + ` FROM ` + iapsTableName + ` WHERE "receiptId" = $1`
85+
err := pgxscan.Get(
86+
ctx,
87+
pool,
88+
res,
89+
query,
90+
pg.Encode(receiptID),
91+
)
92+
if err != nil {
93+
if pgxscan.NotFound(err) {
94+
return nil, iap.ErrNotFound
95+
}
96+
return nil, err
97+
}
98+
return res, nil
99+
}

iap/postgres/server_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"context"
77
"testing"
88

9-
prismatest "github.com/code-payments/flipchat-server/database/prisma/test"
109
"github.com/stretchr/testify/require"
1110

1211
account "github.com/code-payments/flipchat-server/account/postgres"
@@ -22,9 +21,6 @@ func TestChat_PostgresServer(t *testing.T) {
2221
require.NoError(t, err)
2322
defer pool.Close()
2423

25-
client, disconnect := prismatest.NewTestClient(testEnv.DatabaseUrl, t)
26-
defer disconnect()
27-
2824
pub, priv, err := iap_memory.GenerateKeyPair()
2925
if err != nil {
3026
t.Fatalf("error generating key pair: %v", err)
@@ -36,7 +32,7 @@ func TestChat_PostgresServer(t *testing.T) {
3632
}
3733

3834
accounts := account.NewInPostgres(pool)
39-
iaps := NewInPostgres(client)
35+
iaps := NewInPostgres(pool)
4036

4137
teardown := func() {
4238
iaps.(*store).reset()

iap/postgres/store.go

Lines changed: 20 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -4,120 +4,47 @@ import (
44
"context"
55
"errors"
66

7-
commonpb "github.com/code-payments/flipchat-protobuf-api/generated/go/common/v1"
7+
"github.com/jackc/pgx/v5/pgxpool"
88

9-
"github.com/code-payments/code-server/pkg/metrics"
10-
11-
pg "github.com/code-payments/flipchat-server/database/postgres"
12-
"github.com/code-payments/flipchat-server/database/prisma/db"
139
"github.com/code-payments/flipchat-server/iap"
1410
)
1511

16-
const (
17-
metricsStructName = "iap.postgres.store"
18-
)
19-
2012
type store struct {
21-
client *db.PrismaClient
22-
}
23-
24-
func (s *store) reset() {
25-
ctx := context.Background()
26-
27-
purchases := s.client.Iap.FindMany().Delete().Tx()
28-
err := s.client.Prisma.Transaction(purchases).Exec(ctx)
29-
if err != nil {
30-
panic(err)
31-
}
13+
pool *pgxpool.Pool
3214
}
3315

34-
func NewInPostgres(client *db.PrismaClient) iap.Store {
16+
func NewInPostgres(pool *pgxpool.Pool) iap.Store {
3517
return &store{
36-
client,
18+
pool: pool,
3719
}
3820
}
3921

4022
func (s *store) CreatePurchase(ctx context.Context, purchase *iap.Purchase) error {
41-
tracer := metrics.TraceMethodCall(ctx, metricsStructName, "CreatePurchase")
42-
defer tracer.End()
43-
44-
err := func() error {
45-
if purchase.Product != iap.ProductCreateAccount {
46-
return errors.New("product must be create account")
47-
}
48-
if purchase.State != iap.StateFulfilled {
49-
return errors.New("state must be fulfilled")
50-
}
51-
52-
encodedReceiptID := pg.Encode(purchase.ReceiptID)
53-
encodedUserID := pg.Encode(purchase.User.Value)
54-
55-
_, err := s.client.Iap.FindUnique(
56-
db.Iap.ReceiptID.Equals(encodedReceiptID),
57-
).Exec(ctx)
58-
if err == nil {
59-
return iap.ErrExists
60-
} else if !errors.Is(err, db.ErrNotFound) {
61-
return err
62-
}
23+
if purchase.Product != iap.ProductCreateAccount {
24+
return errors.New("product must be create account")
25+
}
26+
if purchase.State != iap.StateFulfilled {
27+
return errors.New("state must be fulfilled")
28+
}
6329

64-
_, err = s.client.Iap.CreateOne(
65-
db.Iap.ReceiptID.Set(encodedReceiptID),
66-
db.Iap.UserID.Set(encodedUserID),
67-
db.Iap.Platform.Set(int(purchase.Platform)),
68-
db.Iap.Product.Set(int(purchase.Product)),
69-
db.Iap.State.Set(int(purchase.State)),
70-
).Exec(ctx)
30+
model, err := toModel(purchase)
31+
if err != nil {
7132
return err
72-
}()
73-
74-
tracer.OnError(err)
75-
76-
return err
33+
}
34+
return model.dbPut(ctx, s.pool)
7735
}
7836

7937
func (s *store) GetPurchase(ctx context.Context, receiptID []byte) (*iap.Purchase, error) {
80-
tracer := metrics.TraceMethodCall(ctx, metricsStructName, "GetPurchase")
81-
defer tracer.End()
82-
83-
res, err := func() (*iap.Purchase, error) {
84-
encodedReceiptID := pg.Encode(receiptID)
85-
86-
res, err := s.client.Iap.FindUnique(
87-
db.Iap.ReceiptID.Equals(encodedReceiptID),
88-
).Exec(ctx)
89-
90-
if errors.Is(err, db.ErrNotFound) {
91-
return nil, iap.ErrNotFound
92-
} else if err != nil {
93-
return nil, err
94-
}
95-
96-
return fromModel(res)
97-
}()
98-
99-
tracer.OnError(err)
100-
101-
return res, err
102-
}
103-
104-
func fromModel(m *db.IapModel) (*iap.Purchase, error) {
105-
decodedReceiptID, err := pg.Decode(m.ReceiptID)
38+
model, err := dbGetPurchase(ctx, s.pool, receiptID)
10639
if err != nil {
10740
return nil, err
10841
}
42+
return fromModel(model)
43+
}
10944

110-
decodedUserID, err := pg.Decode(m.UserID)
45+
func (s *store) reset() {
46+
_, err := s.pool.Exec(context.Background(), "DELETE FROM "+iapsTableName)
11147
if err != nil {
112-
return nil, err
48+
panic(err)
11349
}
114-
115-
return &iap.Purchase{
116-
ReceiptID: decodedReceiptID,
117-
Platform: commonpb.Platform(m.Platform),
118-
User: &commonpb.UserId{Value: decodedUserID},
119-
Product: iap.Product(m.Product),
120-
State: iap.State(m.State),
121-
CreatedAt: m.CreatedAt,
122-
}, nil
12350
}

iap/postgres/store_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@
33
package postgres
44

55
import (
6+
"context"
67
"testing"
78

8-
prismatest "github.com/code-payments/flipchat-server/database/prisma/test"
9+
"github.com/stretchr/testify/require"
910

1011
"github.com/code-payments/flipchat-server/iap/tests"
1112

13+
"github.com/jackc/pgx/v5/pgxpool"
1214
_ "github.com/jackc/pgx/v5/stdlib"
1315
)
1416

1517
func TestIap_PostgresStore(t *testing.T) {
16-
client, disconnect := prismatest.NewTestClient(testEnv.DatabaseUrl, t)
17-
defer disconnect()
18+
pool, err := pgxpool.New(context.Background(), testEnv.DatabaseUrl)
19+
require.NoError(t, err)
20+
defer pool.Close()
1821

19-
testStore := NewInPostgres(client)
22+
testStore := NewInPostgres(pool)
2023
teardown := func() {
2124
testStore.(*store).reset()
2225
}

0 commit comments

Comments
 (0)