Skip to content

Commit 25f900e

Browse files
authored
Ensure that a file overview update is performed even if the initial create connection request takes a long time (#1248)
1 parent 7c102d4 commit 25f900e

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

internal/file/file_manager_service.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ func (fms *FileManagerService) ConfigUpdate(ctx context.Context,
244244
"error", err,
245245
)
246246
}
247+
slog.InfoContext(ctx, "Finished updating file overview")
247248
}
248249

249250
func (fms *FileManagerService) ConfigUpload(ctx context.Context, configUploadRequest *mpi.ConfigUploadRequest) error {

internal/file/file_service_operator.go

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,31 @@ func (fso *FileServiceOperator) UpdateOverview(
132132
},
133133
}
134134

135-
backOffCtx, backoffCancel := context.WithTimeout(newCtx, fso.agentConfig.Client.Backoff.MaxElapsedTime)
136-
defer backoffCancel()
135+
backoffSettings := &config.BackOff{
136+
InitialInterval: fso.agentConfig.Client.Backoff.InitialInterval,
137+
MaxInterval: fso.agentConfig.Client.Backoff.MaxInterval,
138+
MaxElapsedTime: fso.agentConfig.Client.Backoff.MaxElapsedTime,
139+
RandomizationFactor: fso.agentConfig.Client.Backoff.RandomizationFactor,
140+
Multiplier: fso.agentConfig.Client.Backoff.Multiplier,
141+
}
142+
143+
// If the create connection takes a long time that we wait indefinitely to do
144+
// the initial file overview update to ensure that the management plane has a file overview
145+
// on agent startup.
146+
if !fso.isConnected.Load() {
147+
slog.DebugContext(
148+
newCtx,
149+
"Not connected to management plane yet, "+
150+
"retrying indefinitely to update file overview until connection is created",
151+
)
152+
backoffSettings = &config.BackOff{
153+
InitialInterval: fso.agentConfig.Client.Backoff.InitialInterval,
154+
MaxInterval: fso.agentConfig.Client.Backoff.MaxInterval,
155+
MaxElapsedTime: 0,
156+
RandomizationFactor: fso.agentConfig.Client.Backoff.RandomizationFactor,
157+
Multiplier: fso.agentConfig.Client.Backoff.Multiplier,
158+
}
159+
}
137160

138161
sendUpdateOverview := func() (*mpi.UpdateOverviewResponse, error) {
139162
if fso.fileServiceClient == nil {
@@ -162,10 +185,9 @@ func (fso *FileServiceOperator) UpdateOverview(
162185
return response, nil
163186
}
164187

165-
backoffSettings := fso.agentConfig.Client.Backoff
166188
response, err := backoff.RetryWithData(
167189
sendUpdateOverview,
168-
backoffHelpers.Context(backOffCtx, backoffSettings),
190+
backoffHelpers.Context(newCtx, backoffSettings),
169191
)
170192
if err != nil {
171193
return err
@@ -174,11 +196,13 @@ func (fso *FileServiceOperator) UpdateOverview(
174196
slog.DebugContext(newCtx, "UpdateOverview response", "response", response)
175197

176198
if response.GetOverview() == nil {
177-
slog.DebugContext(ctx, "UpdateOverview response is empty")
199+
slog.DebugContext(newCtx, "UpdateOverview response is empty")
178200
return nil
179201
}
180202
delta := files.ConvertToMapOfFiles(response.GetOverview().GetFiles())
181203

204+
// Make sure that the original context is used if a file upload is required so that original correlation ID
205+
// can be used again for update file overview request
182206
if len(delta) != 0 {
183207
return fso.updateFiles(ctx, delta, instanceID, configPath, iteration)
184208
}

internal/file/file_service_operator_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"sync"
1313
"sync/atomic"
1414
"testing"
15+
"time"
1516

1617
mpi "github.com/nginx/agent/v3/api/grpc/mpi/v1"
1718
"github.com/nginx/agent/v3/api/grpc/mpi/v1/v1fakes"
@@ -97,6 +98,30 @@ func TestFileServiceOperator_UpdateOverview_MaxIterations(t *testing.T) {
9798
assert.Equal(t, "too many UpdateOverview attempts", err.Error())
9899
}
99100

101+
func TestFileServiceOperator_UpdateOverview_NoConnection(t *testing.T) {
102+
ctx, cancel := context.WithTimeout(t.Context(), 500*time.Millisecond)
103+
defer cancel()
104+
105+
filePath := filepath.Join(t.TempDir(), "nginx.conf")
106+
fileMeta := protos.FileMeta(filePath, "")
107+
108+
fakeFileServiceClient := &v1fakes.FakeFileServiceClient{}
109+
110+
agentConfig := types.AgentConfig()
111+
agentConfig.Client.Backoff.MaxElapsedTime = 200 * time.Millisecond
112+
113+
fileServiceOperator := NewFileServiceOperator(types.AgentConfig(), fakeFileServiceClient, &sync.RWMutex{})
114+
fileServiceOperator.SetIsConnected(false)
115+
116+
err := fileServiceOperator.UpdateOverview(ctx, "123", []*mpi.File{
117+
{
118+
FileMeta: fileMeta,
119+
},
120+
}, filePath, 0)
121+
122+
assert.ErrorIs(t, err, context.DeadlineExceeded)
123+
}
124+
100125
func TestFileManagerService_UpdateFile(t *testing.T) {
101126
tests := []struct {
102127
name string

0 commit comments

Comments
 (0)