Skip to content

Commit ab40f58

Browse files
committed
Move pagination logic to sql store
Signed-off-by: Joanna Lau <118241363+joannalauu@users.noreply.github.com>
1 parent e5a751c commit ab40f58

File tree

5 files changed

+175
-118
lines changed

5 files changed

+175
-118
lines changed

common/persistence/sql/sql_domain_audit_store.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,26 +93,36 @@ func (m *sqlDomainAuditStore) GetDomainAuditLogs(
9393
ctx context.Context,
9494
request *persistence.GetDomainAuditLogsRequest,
9595
) (*persistence.InternalGetDomainAuditLogsResponse, error) {
96-
var pageTokenMinCreatedTime *time.Time
97-
var pageTokenMinEventID *serialization.UUID
96+
minCreatedTime := time.Unix(0, 0)
97+
maxCreatedTime := time.Now().UTC()
98+
if request.MinCreatedTime != nil {
99+
minCreatedTime = *request.MinCreatedTime
100+
}
101+
if request.MaxCreatedTime != nil {
102+
maxCreatedTime = *request.MaxCreatedTime
103+
}
98104

105+
pageMaxCreatedTime := maxCreatedTime
106+
// if next page token is not present, set pageMinEventID to largest possible uuid
107+
// to prevent the query from returning rows where created_time is equal to pageMaxCreatedTime
108+
pageMinEventID := serialization.UUID{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
99109
if request.NextPageToken != nil {
100110
page := domainAuditLogPageToken{}
101111
if err := gobDeserialize(request.NextPageToken, &page); err != nil {
102112
return nil, fmt.Errorf("unable to decode next page token")
103113
}
104-
pageTokenMinCreatedTime = &page.CreatedTime
105-
pageTokenMinEventID = &page.EventID
114+
pageMaxCreatedTime = page.CreatedTime
115+
pageMinEventID = page.EventID
106116
}
107117

108118
filter := &sqlplugin.DomainAuditLogFilter{
109-
DomainID: serialization.MustParseUUID(request.DomainID),
110-
OperationType: request.OperationType,
111-
MinCreatedTime: request.MinCreatedTime,
112-
MaxCreatedTime: request.MaxCreatedTime,
113-
PageSize: request.PageSize,
114-
PageTokenMinCreatedTime: pageTokenMinCreatedTime,
115-
PageTokenMinEventID: pageTokenMinEventID,
119+
DomainID: serialization.MustParseUUID(request.DomainID),
120+
OperationType: request.OperationType,
121+
MinCreatedTime: &minCreatedTime,
122+
MaxCreatedTime: &maxCreatedTime,
123+
PageSize: request.PageSize,
124+
PageMaxCreatedTime: &pageMaxCreatedTime,
125+
PageMinEventID: &pageMinEventID,
116126
}
117127

118128
rows, err := m.db.SelectFromDomainAuditLogs(ctx, filter)

common/persistence/sql/sql_domain_audit_store_test.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ func TestGetDomainAuditLogs(t *testing.T) {
179179
now := time.Unix(1234567890, 0)
180180
minTime := now.Add(-24 * time.Hour)
181181
maxTime := now
182+
maxUUID := serialization.UUID{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
183+
pageSize := 2
184+
pageSize2 := 3
182185

183186
tests := map[string]struct {
184187
setupMock func(*sqlplugin.MockDB)
@@ -221,13 +224,13 @@ func TestGetDomainAuditLogs(t *testing.T) {
221224
}
222225

223226
expectedFilter := &sqlplugin.DomainAuditLogFilter{
224-
DomainID: serialization.MustParseUUID("d1111111-1111-1111-1111-111111111111"),
225-
OperationType: persistence.DomainAuditOperationTypeUpdate,
226-
MinCreatedTime: &minTime,
227-
MaxCreatedTime: &maxTime,
228-
PageSize: 2,
229-
PageTokenMinCreatedTime: nil,
230-
PageTokenMinEventID: nil,
227+
DomainID: serialization.MustParseUUID("d1111111-1111-1111-1111-111111111111"),
228+
OperationType: persistence.DomainAuditOperationTypeUpdate,
229+
MinCreatedTime: &minTime,
230+
MaxCreatedTime: &maxTime,
231+
PageSize: pageSize,
232+
PageMaxCreatedTime: &maxTime,
233+
PageMinEventID: &maxUUID,
231234
}
232235

233236
dbMock.EXPECT().SelectFromDomainAuditLogs(ctx, expectedFilter).Return(rows, nil).Times(1)
@@ -297,13 +300,13 @@ func TestGetDomainAuditLogs(t *testing.T) {
297300
}
298301

299302
expectedFilter := &sqlplugin.DomainAuditLogFilter{
300-
DomainID: serialization.MustParseUUID("d1111111-1111-1111-1111-111111111111"),
301-
OperationType: persistence.DomainAuditOperationTypeUpdate,
302-
MinCreatedTime: &minTime,
303-
MaxCreatedTime: &maxTime,
304-
PageSize: 3,
305-
PageTokenMinCreatedTime: &expectedCreatedTime,
306-
PageTokenMinEventID: &expectedEventID,
303+
DomainID: serialization.MustParseUUID("d1111111-1111-1111-1111-111111111111"),
304+
OperationType: persistence.DomainAuditOperationTypeUpdate,
305+
MinCreatedTime: &minTime,
306+
MaxCreatedTime: &maxTime,
307+
PageSize: pageSize2,
308+
PageMaxCreatedTime: &expectedCreatedTime,
309+
PageMinEventID: &expectedEventID,
307310
}
308311

309312
dbMock.EXPECT().SelectFromDomainAuditLogs(ctx, expectedFilter).Return(rows, nil).Times(1)

common/persistence/sql/sqlplugin/interfaces.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -597,13 +597,14 @@ type (
597597

598598
// DomainAuditLogFilter contains the filter criteria for querying domain audit logs
599599
DomainAuditLogFilter struct {
600-
DomainID serialization.UUID
601-
OperationType persistence.DomainAuditOperationType
602-
MinCreatedTime *time.Time
603-
MaxCreatedTime *time.Time
604-
PageSize int
605-
PageTokenMinCreatedTime *time.Time
606-
PageTokenMinEventID *serialization.UUID
600+
DomainID serialization.UUID
601+
OperationType persistence.DomainAuditOperationType
602+
MinCreatedTime *time.Time
603+
MaxCreatedTime *time.Time
604+
PageSize int
605+
// PageMaxCreatedTime and PageMinEventID are used to paginate Select queries
606+
PageMaxCreatedTime *time.Time
607+
PageMinEventID *serialization.UUID
607608
}
608609

609610
// tableCRUD defines the API for interacting with the database tables

common/persistence/sql/sqlplugin/postgres/domain_audit_log.go

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ package postgres
2323
import (
2424
"context"
2525
"database/sql"
26-
"fmt"
27-
"time"
2826

2927
"github.com/uber/cadence/common/persistence/sql/sqlplugin"
3028
)
@@ -35,13 +33,22 @@ const (
3533
operation_type, created_time, last_updated_time, identity, identity_type, comment
3634
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`
3735

38-
_selectDomainAuditLogsQuery = `SELECT
36+
_listDomainAuditLogsQuery = `SELECT
3937
event_id, domain_id, state_before, state_before_encoding, state_after, state_after_encoding,
4038
operation_type, created_time, last_updated_time, identity, identity_type, comment
4139
FROM domain_audit_log
42-
WHERE domain_id = $1 AND operation_type = $2 AND created_time >= $3 AND created_time < $4`
40+
WHERE domain_id = $1 AND operation_type = $2 AND created_time >= $3 AND created_time < $4
41+
AND (created_time < $5 OR (created_time = $5 AND event_id > $6))
42+
ORDER BY created_time DESC, event_id ASC
43+
LIMIT $7`
4344

44-
_selectDomainAuditLogsOrderByQuery = ` ORDER BY created_time DESC, event_id ASC`
45+
_getDomainAuditLogsQuery = `SELECT
46+
event_id, domain_id, state_before, state_before_encoding, state_after, state_after_encoding,
47+
operation_type, created_time, last_updated_time, identity, identity_type, comment
48+
FROM domain_audit_log
49+
WHERE domain_id = $1 AND operation_type = $2 AND created_time >= $3 AND created_time < $4
50+
AND (created_time < $5 OR (created_time = $5 AND event_id > $6))
51+
ORDER BY created_time DESC, event_id ASC`
4552
)
4653

4754
// InsertIntoDomainAuditLog inserts a single row into domain_audit_log table
@@ -65,46 +72,37 @@ func (pdb *db) InsertIntoDomainAuditLog(ctx context.Context, row *sqlplugin.Doma
6572
)
6673
}
6774

68-
// SelectFromDomainAuditLogs returns audit log entries for a domain, operation type, and time range (optional)
75+
// SelectFromDomainAuditLogs returns audit log entries for a domain, operation type, and time range
6976
func (pdb *db) SelectFromDomainAuditLogs(
7077
ctx context.Context,
7178
filter *sqlplugin.DomainAuditLogFilter,
7279
) ([]*sqlplugin.DomainAuditLogRow, error) {
73-
74-
start := time.Unix(0, 0)
75-
end := time.Unix(0, time.Now().UnixNano())
76-
77-
if filter.MinCreatedTime != nil {
78-
start = *filter.MinCreatedTime
79-
}
80-
if filter.MaxCreatedTime != nil {
81-
end = *filter.MaxCreatedTime
80+
args := []interface{}{
81+
filter.DomainID,
82+
filter.OperationType,
83+
*filter.MinCreatedTime,
84+
*filter.MaxCreatedTime,
85+
*filter.PageMaxCreatedTime,
86+
*filter.PageMinEventID,
8287
}
8388

84-
// Build base query with all required filters
85-
query := _selectDomainAuditLogsQuery
86-
args := []interface{}{filter.DomainID, filter.OperationType, start, end}
87-
argIndex := 5
88-
89-
// Handle pagination token
90-
if filter.PageTokenMinCreatedTime != nil && filter.PageTokenMinEventID != nil {
91-
query += fmt.Sprintf(` AND (created_time < $%d OR (created_time = $%d AND event_id > $%d))`,
92-
argIndex, argIndex, argIndex+1)
93-
args = append(args, *filter.PageTokenMinCreatedTime, *filter.PageTokenMinEventID)
94-
argIndex += 2
95-
}
96-
97-
query += _selectDomainAuditLogsOrderByQuery
98-
89+
var rows []*sqlplugin.DomainAuditLogRow
9990
if filter.PageSize > 0 {
100-
query += fmt.Sprintf(` LIMIT $%d`, argIndex)
10191
args = append(args, filter.PageSize)
102-
}
92+
err := pdb.driver.SelectContext(ctx, sqlplugin.DbDefaultShard, &rows, _listDomainAuditLogsQuery, args...)
93+
if err != nil {
94+
return nil, err
95+
}
96+
} else {
97+
var row *sqlplugin.DomainAuditLogRow
98+
err := pdb.driver.GetContext(ctx, sqlplugin.DbDefaultShard, &row, _getDomainAuditLogsQuery, args...)
99+
if err != nil {
100+
return nil, err
101+
}
102+
if row != nil {
103+
rows = append(rows, row)
104+
}
103105

104-
var rows []*sqlplugin.DomainAuditLogRow
105-
err := pdb.driver.SelectContext(ctx, sqlplugin.DbDefaultShard, &rows, query, args...)
106-
if err != nil {
107-
return nil, err
108106
}
109107

110108
return rows, nil

0 commit comments

Comments
 (0)