From 4b1c795b25d9870b96b931d1755003e2f73f8e81 Mon Sep 17 00:00:00 2001 From: mschfh <37435502+mschfh@users.noreply.github.com> Date: Mon, 16 Feb 2026 17:45:07 -0500 Subject: [PATCH 1/3] chore(lint): apply golines formatting --- cache/cache.go | 7 +- command/command.go | 87 +++++++++++++++++++--- command/command_test.go | 23 +++++- command/server_defined_unique_entity.go | 8 +- datastore/datastore.go | 16 +++- datastore/datastoretest/mock_datastore.go | 22 +++++- datastore/item_count.go | 10 ++- datastore/item_count_test.go | 6 +- datastore/sync_entity.go | 17 ++++- datastore/sync_entity_test.go | 90 ++++++++++++++++++++--- 10 files changed, 248 insertions(+), 38 deletions(-) diff --git a/cache/cache.go b/cache/cache.go index daeebd4b..9d16fc45 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -54,7 +54,12 @@ func (c *Cache) GetInterimCount(ctx context.Context, clientID string, countType // IncrementInterimCount increments or decrements the amount of entities inserted in // the DB that were not yet added to the item count -func (c *Cache) IncrementInterimCount(ctx context.Context, clientID string, countType string, subtract bool) (int, error) { +func (c *Cache) IncrementInterimCount( + ctx context.Context, + clientID string, + countType string, + subtract bool, +) (int, error) { return c.Incr(ctx, GetInterimCountKey(clientID, countType), subtract) } diff --git a/command/command.go b/command/command.go index 121c7647..3745a8f5 100644 --- a/command/command.go +++ b/command/command.go @@ -34,7 +34,14 @@ const ( // handleGetUpdatesRequest handles GetUpdatesMessage and fills // GetUpdatesResponse. Target sync entities in the database will be updated or // deleted based on the client's requests. -func handleGetUpdatesRequest(ctx context.Context, cache *cache.Cache, guMsg *sync_pb.GetUpdatesMessage, guRsp *sync_pb.GetUpdatesResponse, db datastore.Datastore, clientID string) (*sync_pb.SyncEnums_ErrorType, error) { +func handleGetUpdatesRequest( + ctx context.Context, + cache *cache.Cache, + guMsg *sync_pb.GetUpdatesMessage, + guRsp *sync_pb.GetUpdatesResponse, + db datastore.Datastore, + clientID string, +) (*sync_pb.SyncEnums_ErrorType, error) { errCode := sync_pb.SyncEnums_SUCCESS // default value, might be changed later isNewClient := guMsg.GetUpdatesOrigin != nil && *guMsg.GetUpdatesOrigin == sync_pb.SyncEnums_NEW_CLIENT isPoll := guMsg.GetUpdatesOrigin != nil && *guMsg.GetUpdatesOrigin == sync_pb.SyncEnums_PERIODIC @@ -42,7 +49,14 @@ func handleGetUpdatesRequest(ctx context.Context, cache *cache.Cache, guMsg *syn // Reject the request if client has >= 50 devices in the chain. activeDevices := 0 for { - hasChangesRemaining, syncEntities, err := db.GetUpdatesForType(ctx, deviceInfoTypeID, 0, false, clientID, int64(maxGUBatchSize)) + hasChangesRemaining, syncEntities, err := db.GetUpdatesForType( + ctx, + deviceInfoTypeID, + 0, + false, + clientID, + int64(maxGUBatchSize), + ) if err != nil { log.Error().Err(err).Msgf("db.GetUpdatesForType failed for type %v", deviceInfoTypeID) errCode = sync_pb.SyncEnums_TRANSIENT_ERROR @@ -136,7 +150,14 @@ func handleGetUpdatesRequest(ctx context.Context, cache *cache.Cache, guMsg *syn } curMaxSize := int64(maxSize) - int64(len(guRsp.Entries)) - hasChangesRemaining, entities, err := db.GetUpdatesForType(ctx, int(*fromProgressMarker.DataTypeId), token, fetchFolders, clientID, curMaxSize) + hasChangesRemaining, entities, err := db.GetUpdatesForType( + ctx, + int(*fromProgressMarker.DataTypeId), + token, + fetchFolders, + clientID, + curMaxSize, + ) if err != nil { log.Error().Err(err).Msgf("db.GetUpdatesForType failed for type %v", *fromProgressMarker.DataTypeId) errCode = sync_pb.SyncEnums_TRANSIENT_ERROR @@ -195,7 +216,12 @@ func handleGetUpdatesRequest(ctx context.Context, cache *cache.Cache, guMsg *syn return &errCode, nil } -func getItemCounts(ctx context.Context, cache *cache.Cache, db datastore.Datastore, clientID string) (*datastore.ClientItemCounts, int, int, error) { +func getItemCounts( + ctx context.Context, + cache *cache.Cache, + db datastore.Datastore, + clientID string, +) (*datastore.ClientItemCounts, int, int, error) { itemCounts, err := db.GetClientItemCount(ctx, clientID) if err != nil { return nil, 0, 0, err @@ -223,7 +249,14 @@ func getInterimItemCounts(ctx context.Context, cache *cache.Cache, clientID stri // For each commit entry: // - new sync entity is created and inserted into the database if version is 0. // - existed sync entity will be updated if version is greater than 0. -func handleCommitRequest(ctx context.Context, cache *cache.Cache, commitMsg *sync_pb.CommitMessage, commitRsp *sync_pb.CommitResponse, db datastore.Datastore, clientID string) (*sync_pb.SyncEnums_ErrorType, error) { +func handleCommitRequest( + ctx context.Context, + cache *cache.Cache, + commitMsg *sync_pb.CommitMessage, + commitRsp *sync_pb.CommitResponse, + db datastore.Datastore, + clientID string, +) (*sync_pb.SyncEnums_ErrorType, error) { if commitMsg == nil { return nil, errors.New("nil commitMsg is received") } @@ -249,7 +282,10 @@ func handleCommitRequest(ctx context.Context, cache *cache.Cache, commitMsg *syn // "Boost" the quota with the difference between the history quota and count, // so users can start syncing other entities immediately, instead of waiting for the // history TTL to get rid of the excess items. - boostedQuotaAddition = min(maxClientObjectQuota-maxClientHistoryObjectQuota, currentHistoryItemCount-maxClientHistoryObjectQuota) + boostedQuotaAddition = min( + maxClientObjectQuota-maxClientHistoryObjectQuota, + currentHistoryItemCount-maxClientHistoryObjectQuota, + ) } commitRsp.Entryresponse = make([]*sync_pb.CommitResponse_EntryResponse, len(commitMsg.Entries)) @@ -266,7 +302,9 @@ func handleCommitRequest(ctx context.Context, cache *cache.Cache, commitMsg *syn if err != nil { // Can't unmarshal & marshal the message from PB into DB format rspType := sync_pb.CommitResponse_INVALID_MESSAGE entryRsp.ResponseType = &rspType - entryRsp.ErrorMessage = aws.String(fmt.Sprintf("Cannot convert protobuf sync entity to DB format: %v", err.Error())) + entryRsp.ErrorMessage = aws.String( + fmt.Sprintf("Cannot convert protobuf sync entity to DB format: %v", err.Error()), + ) continue } @@ -280,7 +318,8 @@ func handleCommitRequest(ctx context.Context, cache *cache.Cache, commitMsg *syn oldVersion := *entityToCommit.Version isUpdateOp := oldVersion != 0 - isHistoryRelatedItem := *entityToCommit.DataType == datastore.HistoryTypeID || *entityToCommit.DataType == datastore.HistoryDeleteDirectiveTypeID + isHistoryRelatedItem := *entityToCommit.DataType == datastore.HistoryTypeID || + *entityToCommit.DataType == datastore.HistoryDeleteDirectiveTypeID *entityToCommit.Version = *entityToCommit.Mtime if *entityToCommit.DataType == datastore.HistoryTypeID { // Check if item exists using client_unique_tag @@ -299,7 +338,12 @@ func handleCommitRequest(ctx context.Context, cache *cache.Cache, commitMsg *syn if currentNormalItemCount+currentHistoryItemCount+newNormalCount+newHistoryCount >= maxClientObjectQuota+boostedQuotaAddition { rspType := sync_pb.CommitResponse_OVER_QUOTA entryRsp.ResponseType = &rspType - entryRsp.ErrorMessage = aws.String(fmt.Sprintf("There are already %v non-deleted objects in store", currentNormalItemCount+currentHistoryItemCount)) + entryRsp.ErrorMessage = aws.String( + fmt.Sprintf( + "There are already %v non-deleted objects in store", + currentNormalItemCount+currentHistoryItemCount, + ), + ) continue } @@ -397,7 +441,13 @@ func handleCommitRequest(ctx context.Context, cache *cache.Cache, commitMsg *syn // handleClearServerDataRequest handles clearing user data from the datastore and cache // and fills the response -func handleClearServerDataRequest(ctx context.Context, cache *cache.Cache, db datastore.Datastore, _ *sync_pb.ClearServerDataMessage, clientID string) (*sync_pb.SyncEnums_ErrorType, error) { +func handleClearServerDataRequest( + ctx context.Context, + cache *cache.Cache, + db datastore.Datastore, + _ *sync_pb.ClearServerDataMessage, + clientID string, +) (*sync_pb.SyncEnums_ErrorType, error) { errCode := sync_pb.SyncEnums_SUCCESS var err error @@ -435,7 +485,14 @@ func handleClearServerDataRequest(ctx context.Context, cache *cache.Cache, db da // HandleClientToServerMessage handles the protobuf ClientToServerMessage and // fills the protobuf ClientToServerResponse. -func HandleClientToServerMessage(ctx context.Context, cache *cache.Cache, pb *sync_pb.ClientToServerMessage, pbRsp *sync_pb.ClientToServerResponse, db datastore.Datastore, clientID string) error { +func HandleClientToServerMessage( + ctx context.Context, + cache *cache.Cache, + pb *sync_pb.ClientToServerMessage, + pbRsp *sync_pb.ClientToServerResponse, + db datastore.Datastore, + clientID string, +) error { // Create ClientToServerResponse and fill general fields for both GU and // Commit. pbRsp.StoreBirthday = aws.String(storeBirthday) @@ -477,7 +534,13 @@ func HandleClientToServerMessage(ctx context.Context, cache *cache.Cache, pb *sy } else if *pb.MessageContents == sync_pb.ClientToServerMessage_CLEAR_SERVER_DATA { csdRsp := &sync_pb.ClearServerDataResponse{} pbRsp.ClearServerData = csdRsp - pbRsp.ErrorCode, err = handleClearServerDataRequest(context.Background(), cache, db, pb.ClearServerData, clientID) + pbRsp.ErrorCode, err = handleClearServerDataRequest( + context.Background(), + cache, + db, + pb.ClearServerData, + clientID, + ) if err != nil { if pbRsp.ErrorCode != nil { pbRsp.ErrorMessage = aws.String(err.Error()) diff --git a/command/command_test.go b/command/command_test.go index 1f8bb3c9..b7d8f0d8 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -49,7 +49,14 @@ func (a PBSyncAttrsByName) Len() int { return len(a) } func (a PBSyncAttrsByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a PBSyncAttrsByName) Less(i, j int) bool { return *a[i].Name < *a[j].Name } -func NewPBSyncAttrs(name *string, version *int64, deleted *bool, folder *bool, serverTag *string, specifics *sync_pb.EntitySpecifics) *PBSyncAttrs { +func NewPBSyncAttrs( + name *string, + version *int64, + deleted *bool, + folder *bool, + serverTag *string, + specifics *sync_pb.EntitySpecifics, +) *PBSyncAttrs { return &PBSyncAttrs{ Name: name, Version: version, @@ -421,7 +428,12 @@ func (suite *CommandTestSuite) TestHandleClientToServerMessage_DeviceLimitExceed suite.Require().NoError( command.HandleClientToServerMessage(context.Background(), suite.cache, commitMsg, commitRsp, suite.dynamo, testCase.clientID), "Commit device info should succeed for device %d", i) - suite.Equal(sync_pb.SyncEnums_SUCCESS, *commitRsp.ErrorCode, "Commit device info should succeed for device %d", i) + suite.Equal( + sync_pb.SyncEnums_SUCCESS, + *commitRsp.ErrorCode, + "Commit device info should succeed for device %d", + i, + ) } // should get THROTTLED error when device limit is exceeded @@ -598,7 +610,12 @@ func (suite *CommandTestSuite) TestHandleClientToServerMessage_ReplaceParentIDTo child3 := getCommitEntity("id_child3", 0, false, getBookmarkSpecifics()) child3.ParentIdString = aws.String("id_parent2") - updateChild0 := getCommitEntity(*rsp.Commit.Entryresponse[0].IdString, *rsp.Commit.Entryresponse[0].Version, false, getBookmarkSpecifics()) + updateChild0 := getCommitEntity( + *rsp.Commit.Entryresponse[0].IdString, + *rsp.Commit.Entryresponse[0].Version, + false, + getBookmarkSpecifics(), + ) updateChild0.ParentIdString = aws.String("id_parent") entries := []*sync_pb.SyncEntity{parent1, child1, parent2, child2, child3, updateChild0} diff --git a/command/server_defined_unique_entity.go b/command/server_defined_unique_entity.go index 60927924..825825a6 100644 --- a/command/server_defined_unique_entity.go +++ b/command/server_defined_unique_entity.go @@ -25,7 +25,13 @@ const ( bookmarkBarTag string = "bookmark_bar" ) -func createServerDefinedUniqueEntity(name string, serverDefinedTag string, clientID string, parentID string, specifics *sync_pb.EntitySpecifics) (*datastore.SyncEntity, error) { +func createServerDefinedUniqueEntity( + name string, + serverDefinedTag string, + clientID string, + parentID string, + specifics *sync_pb.EntitySpecifics, +) (*datastore.SyncEntity, error) { now := time.Now().UnixMilli() deleted := false folder := true diff --git a/datastore/datastore.go b/datastore/datastore.go index 217642f9..a4b6daaa 100644 --- a/datastore/datastore.go +++ b/datastore/datastore.go @@ -14,13 +14,25 @@ type Datastore interface { // client token for a given client. Besides the array of sync entities, a // boolean value indicating whether there are more updates to query in the // next batch is returned. - GetUpdatesForType(ctx context.Context, dataType int, clientToken int64, fetchFolders bool, clientID string, maxSize int64) (bool, []SyncEntity, error) + GetUpdatesForType( + ctx context.Context, + dataType int, + clientToken int64, + fetchFolders bool, + clientID string, + maxSize int64, + ) (bool, []SyncEntity, error) // Check if a server-defined unique tag is in the datastore. HasServerDefinedUniqueTag(ctx context.Context, clientID string, tag string) (bool, error) // Get the count of sync items for a client. GetClientItemCount(ctx context.Context, clientID string) (*ClientItemCounts, error) // Update the count of sync items for a client. - UpdateClientItemCount(ctx context.Context, counts *ClientItemCounts, newNormalItemCount int, newHistoryItemCount int) error + UpdateClientItemCount( + ctx context.Context, + counts *ClientItemCounts, + newNormalItemCount int, + newHistoryItemCount int, + ) error // ClearServerData deletes all items for a given clientID ClearServerData(ctx context.Context, clientID string) ([]SyncEntity, error) // DisableSyncChain marks a chain as disabled so no further updates or commits can happen diff --git a/datastore/datastoretest/mock_datastore.go b/datastore/datastoretest/mock_datastore.go index 150d3b0c..47871a32 100644 --- a/datastore/datastoretest/mock_datastore.go +++ b/datastore/datastoretest/mock_datastore.go @@ -26,13 +26,24 @@ func (m *MockDatastore) InsertSyncEntitiesWithServerTags(ctx context.Context, en } // UpdateSyncEntity mocks calls to UpdateSyncEntity -func (m *MockDatastore) UpdateSyncEntity(ctx context.Context, entity *datastore.SyncEntity, oldVersion int64) (conflict bool, deleted bool, err error) { +func (m *MockDatastore) UpdateSyncEntity( + ctx context.Context, + entity *datastore.SyncEntity, + oldVersion int64, +) (conflict bool, deleted bool, err error) { args := m.Called(ctx, entity, oldVersion) return args.Bool(0), args.Bool(1), args.Error(2) } // GetUpdatesForType mocks calls to GetUpdatesForType -func (m *MockDatastore) GetUpdatesForType(ctx context.Context, dataType int, clientToken int64, fetchFolders bool, clientID string, maxSize int64) (bool, []datastore.SyncEntity, error) { +func (m *MockDatastore) GetUpdatesForType( + ctx context.Context, + dataType int, + clientToken int64, + fetchFolders bool, + clientID string, + maxSize int64, +) (bool, []datastore.SyncEntity, error) { args := m.Called(ctx, dataType, clientToken, fetchFolders, clientID, maxSize) return args.Bool(0), args.Get(1).([]datastore.SyncEntity), args.Error(2) } @@ -55,7 +66,12 @@ func (m *MockDatastore) GetClientItemCount(ctx context.Context, clientID string) } // UpdateClientItemCount mocks calls to UpdateClientItemCount -func (m *MockDatastore) UpdateClientItemCount(ctx context.Context, counts *datastore.ClientItemCounts, newNormalItemCount int, newHistoryItemCount int) error { +func (m *MockDatastore) UpdateClientItemCount( + ctx context.Context, + counts *datastore.ClientItemCounts, + newNormalItemCount int, + newHistoryItemCount int, +) error { args := m.Called(ctx, counts, newNormalItemCount, newHistoryItemCount) return args.Error(0) } diff --git a/datastore/item_count.go b/datastore/item_count.go index a5b2f671..40c18f72 100644 --- a/datastore/item_count.go +++ b/datastore/item_count.go @@ -60,7 +60,8 @@ func (dynamo *Dynamo) initRealCountsAndUpdateHistoryCounts(ctx context.Context, // Query the DB to get updated counts pkCond := expression.Key(clientIDDataTypeMtimeIdxPk).Equal(expression.Value(counts.ClientID)) filterCond := expression.And( - expression.Name(dataTypeAttrName).In(expression.Value(HistoryTypeID), expression.Value(HistoryDeleteDirectiveTypeID)), + expression.Name(dataTypeAttrName). + In(expression.Value(HistoryTypeID), expression.Value(HistoryDeleteDirectiveTypeID)), expression.Name(deletedAttrName).Equal(expression.Value(false)), ) expr, err := expression.NewBuilder().WithKeyCondition(pkCond).WithFilter(filterCond).Build() @@ -166,7 +167,12 @@ func (dynamo *Dynamo) GetClientItemCount(ctx context.Context, clientID string) ( // UpdateClientItemCount updates the count of non-deleted sync items for a // given client stored in the dynamoDB. -func (dynamo *Dynamo) UpdateClientItemCount(ctx context.Context, counts *ClientItemCounts, newNormalItemCount int, newHistoryItemCount int) error { +func (dynamo *Dynamo) UpdateClientItemCount( + ctx context.Context, + counts *ClientItemCounts, + newNormalItemCount int, + newHistoryItemCount int, +) error { counts.HistoryItemCountPeriod4 += newHistoryItemCount counts.ItemCount += newNormalItemCount diff --git a/datastore/item_count_test.go b/datastore/item_count_test.go index ada6f745..1122d845 100644 --- a/datastore/item_count_test.go +++ b/datastore/item_count_test.go @@ -41,7 +41,11 @@ func (suite *ItemCountTestSuite) TestGetClientItemCount() { {ClientID: "client2", ID: "client2", ItemCount: 10}, } for _, item := range items { - existing := datastore.ClientItemCounts{ClientID: item.ClientID, ID: item.ID, Version: datastore.CurrentCountVersion} + existing := datastore.ClientItemCounts{ + ClientID: item.ClientID, + ID: item.ID, + Version: datastore.CurrentCountVersion, + } suite.Require().NoError( suite.dynamo.UpdateClientItemCount(context.Background(), &existing, item.ItemCount, 0)) } diff --git a/datastore/sync_entity.go b/datastore/sync_entity.go index 144ea3ec..016dee19 100644 --- a/datastore/sync_entity.go +++ b/datastore/sync_entity.go @@ -216,7 +216,10 @@ func (dynamo *Dynamo) InsertSyncEntity(ctx context.Context, entity *SyncEntity) } } } - return false, fmt.Errorf("error writing tag item and sync item in a transaction to insert sync entity: %w", err) + return false, fmt.Errorf( + "error writing tag item and sync item in a transaction to insert sync entity: %w", + err, + ) } return false, nil @@ -538,7 +541,8 @@ func (dynamo *Dynamo) UpdateSyncEntity(ctx context.Context, entity *SyncEntity, // Soft-delete a sync item with a client tag, use a transaction to delete its // tag item too. - if entity.Deleted != nil && entity.ClientDefinedUniqueTag != nil && *entity.Deleted && *entity.DataType != HistoryTypeID { + if entity.Deleted != nil && entity.ClientDefinedUniqueTag != nil && *entity.Deleted && + *entity.DataType != HistoryTypeID { pk := PrimaryKey{ ClientID: entity.ClientID, ID: clientTagItemPrefix + *entity.ClientDefinedUniqueTag} tagItemKey, err := attributevalue.MarshalMap(pk) @@ -631,7 +635,14 @@ func (dynamo *Dynamo) UpdateSyncEntity(ctx context.Context, entity *SyncEntity, // To do this in dynamoDB, we use (ClientID, DataType#Mtime) as GSI to get a // list of (ClientID, ID) primary keys with the given condition, then read the // actual sync item using the list of primary keys. -func (dynamo *Dynamo) GetUpdatesForType(ctx context.Context, dataType int, clientToken int64, fetchFolders bool, clientID string, maxSize int64) (bool, []SyncEntity, error) { +func (dynamo *Dynamo) GetUpdatesForType( + ctx context.Context, + dataType int, + clientToken int64, + fetchFolders bool, + clientID string, + maxSize int64, +) (bool, []SyncEntity, error) { syncEntities := []SyncEntity{} // Get (ClientID, ID) pairs which are updates after mtime for a data type, diff --git a/datastore/sync_entity_test.go b/datastore/sync_entity_test.go index 231af3b9..97476fdd 100644 --- a/datastore/sync_entity_test.go +++ b/datastore/sync_entity_test.go @@ -554,51 +554,107 @@ func (suite *SyncEntityTestSuite) TestGetUpdatesForType() { suite.Require().NoError(err, "InsertSyncEntity should succeed") // Get all updates for type 123 and client1 using token = 0. - hasChangesRemaining, syncItems, err := suite.dynamo.GetUpdatesForType(context.Background(), 123, 0, true, "client1", 100) + hasChangesRemaining, syncItems, err := suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 0, + true, + "client1", + 100, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal([]datastore.SyncEntity{entity1, entity2}, syncItems) suite.False(hasChangesRemaining) // Get all updates for type 124 and client1 using token = 0. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 124, 0, true, "client1", 100) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 124, + 0, + true, + "client1", + 100, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal([]datastore.SyncEntity{entity3}, syncItems) suite.False(hasChangesRemaining) // Get all updates for type 123 and client2 using token = 0. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 123, 0, true, "client2", 100) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 0, + true, + "client2", + 100, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal([]datastore.SyncEntity{entity4}, syncItems) suite.False(hasChangesRemaining) // Get all updates for type 124 and client2 using token = 0. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 124, 0, true, "client2", 100) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 124, + 0, + true, + "client2", + 100, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Empty(syncItems) suite.False(hasChangesRemaining) // Test maxSize will limit the return entries size, and hasChangesRemaining // should be true when there are more updates available in the DB. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 123, 0, true, "client1", 1) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 0, + true, + "client1", + 1, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal([]datastore.SyncEntity{entity1}, syncItems) suite.True(hasChangesRemaining) // Test when num of query items equal to the limit, hasChangesRemaining should // be true. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 123, 0, true, "client1", 2) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 0, + true, + "client1", + 2, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal([]datastore.SyncEntity{entity1, entity2}, syncItems) suite.True(hasChangesRemaining) // Test fetchFolders will remove folder items if false - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 123, 0, false, "client1", 100) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 0, + false, + "client1", + 100, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal([]datastore.SyncEntity{entity2}, syncItems) suite.False(hasChangesRemaining) // Get all updates for a type for a client using mtime of one item as token. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 123, 12345678, true, "client1", 100) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 12345678, + true, + "client1", + 100, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal([]datastore.SyncEntity{entity2}, syncItems) suite.False(hasChangesRemaining) @@ -631,7 +687,14 @@ func (suite *SyncEntityTestSuite) TestGetUpdatesForType() { } // All items should be returned and sorted by Mtime. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 123, 0, true, "client1", 300) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 0, + true, + "client1", + 300, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") sort.Sort(datastore.SyncEntityByMtime(expectedSyncItems)) suite.Equal(expectedSyncItems, syncItems) @@ -639,7 +702,14 @@ func (suite *SyncEntityTestSuite) TestGetUpdatesForType() { // Test that when maxGUBatchSize is smaller than total updates, the first n // items ordered by Mtime should be returned. - hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType(context.Background(), 123, 0, true, "client1", 200) + hasChangesRemaining, syncItems, err = suite.dynamo.GetUpdatesForType( + context.Background(), + 123, + 0, + true, + "client1", + 200, + ) suite.Require().NoError(err, "GetUpdatesForType should succeed") suite.Equal(syncItems, expectedSyncItems[0:200]) suite.True(hasChangesRemaining) From af95aa92cdf48a60ca3351b1eae33fe3a9ba1ac9 Mon Sep 17 00:00:00 2001 From: mschfh <37435502+mschfh@users.noreply.github.com> Date: Mon, 16 Feb 2026 23:56:43 -0500 Subject: [PATCH 2/3] chore(lint): fix gosec findings --- auth/auth.go | 2 +- server/server.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/auth/auth.go b/auth/auth.go index 06d52402..dfd3b4ff 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -19,7 +19,7 @@ const ( // TokenMaxDuration specifies the lifetime for each access token. TokenMaxDuration int64 = 86400 * 1e3 // Milliseconds bearerPrefix string = "Bearer " - tokenRE string = `^(?P[a-fA-F0-9]+)\|(?P[a-fA-F0-9]+)\|(?P[a-fA-F0-9]+)$` + tokenRE string = `^(?P[a-fA-F0-9]+)\|(?P[a-fA-F0-9]+)\|(?P[a-fA-F0-9]+)$` //nolint:gosec // G101 false positive: regex pattern, not a credential ) // Token represents the values we have in access tokens. diff --git a/server/server.go b/server/server.go index f9b38b31..b9d5fefb 100644 --- a/server/server.go +++ b/server/server.go @@ -5,7 +5,7 @@ import ( "fmt" "net" "net/http" - _ "net/http/pprof" // pprof magic + _ "net/http/pprof" //nolint:gosec // G108: pprof is served on a separate listener (:6061), gated by PPROF_ENABLED "os" "os/signal" "strconv" @@ -142,7 +142,7 @@ func StartServer() { healthCheckActive = false // disable health check time.Sleep(60 * time.Second) - //nolint:errcheck // Error during shutdown in signal handler is acceptable + //nolint:errcheck,gosec // Error during shutdown in signal handler is acceptable srv.Shutdown(serverCtx) }() @@ -151,6 +151,7 @@ func StartServer() { // pprof attaches routes to default serve mux // host:6061/debug/pprof/ go func() { + //nolint:gosec // G114: pprof diagnostic server if err := http.ListenAndServe(":6061", http.DefaultServeMux); err != nil { log.Err(err).Msg("pprof service returned error") } From 88ec86a8b8c73477a10376a2f885a6af2bc43930 Mon Sep 17 00:00:00 2001 From: mschfh <37435502+mschfh@users.noreply.github.com> Date: Tue, 24 Feb 2026 14:31:23 -0500 Subject: [PATCH 3/3] chore(lint): fix gosec findings --- command/command.go | 12 ++++++------ datastore/datastore.go | 2 +- datastore/datastoretest/mock_datastore.go | 2 +- datastore/instrumented_datastore.go | 2 +- datastore/sync_entity.go | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/command/command.go b/command/command.go index 3745a8f5..0f4defb0 100644 --- a/command/command.go +++ b/command/command.go @@ -16,9 +16,9 @@ import ( var ( // Could be modified in tests. - maxGUBatchSize = 500 - maxClientObjectQuota = 50000 - maxClientHistoryObjectQuota = 30000 + maxGUBatchSize int32 = 500 + maxClientObjectQuota = 50000 + maxClientHistoryObjectQuota = 30000 ) const ( @@ -55,7 +55,7 @@ func handleGetUpdatesRequest( 0, false, clientID, - int64(maxGUBatchSize), + maxGUBatchSize, ) if err != nil { log.Error().Err(err).Msgf("db.GetUpdatesForType failed for type %v", deviceInfoTypeID) @@ -134,7 +134,7 @@ func handleGetUpdatesRequest( // of break because we need to prepare NewProgressMarker for all entries in // FromProgressMarker, where the returned token stays the same as the one // passed in FromProgressMarker. - if len(guRsp.Entries) >= maxSize { + if len(guRsp.Entries) >= int(maxSize) { continue } @@ -149,7 +149,7 @@ func handleGetUpdatesRequest( continue } - curMaxSize := int64(maxSize) - int64(len(guRsp.Entries)) + curMaxSize := int32(int(maxSize) - len(guRsp.Entries)) //nolint:gosec // maxSize is 500 and the >= check above ensures entries fits within it hasChangesRemaining, entities, err := db.GetUpdatesForType( ctx, int(*fromProgressMarker.DataTypeId), diff --git a/datastore/datastore.go b/datastore/datastore.go index a4b6daaa..2f83da3c 100644 --- a/datastore/datastore.go +++ b/datastore/datastore.go @@ -20,7 +20,7 @@ type Datastore interface { clientToken int64, fetchFolders bool, clientID string, - maxSize int64, + maxSize int32, ) (bool, []SyncEntity, error) // Check if a server-defined unique tag is in the datastore. HasServerDefinedUniqueTag(ctx context.Context, clientID string, tag string) (bool, error) diff --git a/datastore/datastoretest/mock_datastore.go b/datastore/datastoretest/mock_datastore.go index 47871a32..0e305903 100644 --- a/datastore/datastoretest/mock_datastore.go +++ b/datastore/datastoretest/mock_datastore.go @@ -42,7 +42,7 @@ func (m *MockDatastore) GetUpdatesForType( clientToken int64, fetchFolders bool, clientID string, - maxSize int64, + maxSize int32, ) (bool, []datastore.SyncEntity, error) { args := m.Called(ctx, dataType, clientToken, fetchFolders, clientID, maxSize) return args.Bool(0), args.Get(1).([]datastore.SyncEntity), args.Error(2) diff --git a/datastore/instrumented_datastore.go b/datastore/instrumented_datastore.go index 2abecd13..c068d8f8 100644 --- a/datastore/instrumented_datastore.go +++ b/datastore/instrumented_datastore.go @@ -81,7 +81,7 @@ func (_d DatastoreWithPrometheus) GetClientItemCount(ctx context.Context, client } // GetUpdatesForType implements Datastore -func (_d DatastoreWithPrometheus) GetUpdatesForType(ctx context.Context, dataType int, clientToken int64, fetchFolders bool, clientID string, maxSize int64) (b1 bool, sa1 []SyncEntity, err error) { +func (_d DatastoreWithPrometheus) GetUpdatesForType(ctx context.Context, dataType int, clientToken int64, fetchFolders bool, clientID string, maxSize int32) (b1 bool, sa1 []SyncEntity, err error) { _since := time.Now() defer func() { result := "ok" diff --git a/datastore/sync_entity.go b/datastore/sync_entity.go index 016dee19..56b6f825 100644 --- a/datastore/sync_entity.go +++ b/datastore/sync_entity.go @@ -641,7 +641,7 @@ func (dynamo *Dynamo) GetUpdatesForType( clientToken int64, fetchFolders bool, clientID string, - maxSize int64, + maxSize int32, ) (bool, []SyncEntity, error) { syncEntities := []SyncEntity{} @@ -675,7 +675,7 @@ func (dynamo *Dynamo) GetUpdatesForType( FilterExpression: expr.Filter(), ProjectionExpression: aws.String(projPk), TableName: aws.String(Table), - Limit: aws.Int32(int32(maxSize)), + Limit: aws.Int32(maxSize), } out, err := dynamo.Query(ctx, input)