diff --git a/backend/LexBoxApi/Services/HgService.cs b/backend/LexBoxApi/Services/HgService.cs index 15a0cfa77..688928ab9 100644 --- a/backend/LexBoxApi/Services/HgService.cs +++ b/backend/LexBoxApi/Services/HgService.cs @@ -67,6 +67,7 @@ await Task.Run(() => { InitRepoAt(new DirectoryInfo(PrefixRepoFilePath(code))); }); + await InvalidateDirCache(code); } private void InitRepoAt(DirectoryInfo repoDirectory) @@ -82,6 +83,7 @@ private void InitRepoAt(DirectoryInfo repoDirectory) public async Task DeleteRepo(string code) { await Task.Run(() => Directory.Delete(PrefixRepoFilePath(code), true)); + await InvalidateDirCache(code); } public BackupExecutor? BackupRepo(string code) @@ -104,6 +106,7 @@ public async Task ResetRepo(string code) await SoftDeleteRepo(code, $"{FileUtils.ToTimestamp(DateTimeOffset.UtcNow)}__reset"); //we must init the repo as uploading a zip is optional tmpRepo.MoveTo(PrefixRepoFilePath(code)); + await InvalidateDirCache(code); } public async Task FinishReset(string code, Stream zipFile) @@ -137,6 +140,7 @@ await Task.Run(() => // Now we're ready to move the new repo into place, replacing the old one await DeleteRepo(code); tempRepo.MoveTo(PrefixRepoFilePath(code)); + await InvalidateDirCache(code); } /// @@ -181,6 +185,7 @@ await Task.Run(() => PrefixRepoFilePath(code), Path.Combine(deletedRepoPath, deletedRepoName)); }); + await InvalidateDirCache(code); } private const UnixFileMode Permissions = UnixFileMode.GroupRead | UnixFileMode.GroupWrite | @@ -262,6 +267,11 @@ public async Task ExecuteHgRecover(string code, CancellationToken t return response; } + public async Task InvalidateDirCache(string code) + { + await ExecuteHgCommandServerCommand(code, "invalidatedircache", default); + } + public async Task GetLexEntryCount(string code, ProjectType projectType) { var command = projectType switch diff --git a/backend/Testing/ApiTests/ApiTestBase.cs b/backend/Testing/ApiTests/ApiTestBase.cs index fd448361c..89db65d10 100644 --- a/backend/Testing/ApiTests/ApiTestBase.cs +++ b/backend/Testing/ApiTests/ApiTestBase.cs @@ -60,10 +60,4 @@ public async Task StartLexboxProjectReset(string projectCode) var response = await HttpClient.PostAsync($"{BaseUrl}/api/project/resetProject/{projectCode}", null); response.EnsureSuccessStatusCode(); } - - public async Task InvalidateDirCache(string projectCode) - { - var response = await HttpClient.PostAsync($"{BaseUrl}/hg/command/{projectCode}/invalidatedircache", null); - response.EnsureSuccessStatusCode(); - } } diff --git a/backend/Testing/ApiTests/NewProjectRaceCondition.cs b/backend/Testing/ApiTests/NewProjectRaceCondition.cs index b756b050b..2eed7b63b 100644 --- a/backend/Testing/ApiTests/NewProjectRaceCondition.cs +++ b/backend/Testing/ApiTests/NewProjectRaceCondition.cs @@ -51,8 +51,6 @@ private async Task CreateQueryAndVerifyProject(Guid id) } """); - await InvalidateDirCache($"{id}"); - var project = response["data"]!["createProject"]!["createProjectResponse"].ShouldBeOfType(); project["id"]!.GetValue().ShouldBe(id.ToString()); diff --git a/backend/Testing/Services/Utils.cs b/backend/Testing/Services/Utils.cs index 767868820..dd8a6559d 100644 --- a/backend/Testing/Services/Utils.cs +++ b/backend/Testing/Services/Utils.cs @@ -61,7 +61,6 @@ ... on DbError { } } """); - await apiTester.InvalidateDirCache(config.Code); // Ensure newly-created project is available right away return new LexboxProject(apiTester, config.Id); } diff --git a/backend/Testing/SyncReverseProxy/SendReceiveServiceTests.cs b/backend/Testing/SyncReverseProxy/SendReceiveServiceTests.cs index 0ae4b118e..baa0bd71e 100644 --- a/backend/Testing/SyncReverseProxy/SendReceiveServiceTests.cs +++ b/backend/Testing/SyncReverseProxy/SendReceiveServiceTests.cs @@ -85,8 +85,6 @@ public async Task ModifyProjectData(HgProtocol protocol) var sendReceiveParams = new SendReceiveParams(protocol, projectConfig); _sendReceiveService.SendReceiveProject(sendReceiveParams, AdminAuth); - await _adminApiTester.InvalidateDirCache(projectConfig.Code); - // Verify pushed and store last commit var lastCommitDate = await _adminApiTester.GetProjectLastCommit(projectConfig.Code); lastCommitDate.ShouldNotBeNullOrEmpty(); @@ -99,8 +97,6 @@ public async Task ModifyProjectData(HgProtocol protocol) // Push changes _sendReceiveService.SendReceiveProject(sendReceiveParams, AdminAuth, "Modify project data automated test"); - await _adminApiTester.InvalidateDirCache(projectConfig.Code); - // Verify the push updated the last commit date var lastCommitDateAfter = await _adminApiTester.GetProjectLastCommit(projectConfig.Code); lastCommitDateAfter.ShouldBeGreaterThan(lastCommitDate); @@ -140,8 +136,6 @@ public async Task SendReceiveAfterProjectReset(HgProtocol protocol) await _adminApiTester.HttpClient.PostAsync($"{_adminApiTester.BaseUrl}/api/project/resetProject/{projectConfig.Code}", null); await _adminApiTester.HttpClient.PostAsync($"{_adminApiTester.BaseUrl}/api/project/finishResetProject/{projectConfig.Code}", null); - await _adminApiTester.InvalidateDirCache(projectConfig.Code); - // Step 2: verify project is now empty, i.e. tip is "0000000..." response = await _adminApiTester.HttpClient.GetAsync(tipUri.Uri); jsonResult = await response.Content.ReadFromJsonAsync(); @@ -165,8 +159,6 @@ public async Task SendReceiveAfterProjectReset(HgProtocol protocol) var srResultStep3 = _sendReceiveService.SendReceiveProject(sendReceiveParams, AdminAuth); _output.WriteLine(srResultStep3); - await _adminApiTester.InvalidateDirCache(projectConfig.Code); - // Step 4: verify project tip is same hash as original project tip response = await _adminApiTester.HttpClient.GetAsync(tipUri.Uri); jsonResult = await response.Content.ReadFromJsonAsync(); diff --git a/frontend/tests/resetProject.test.ts b/frontend/tests/resetProject.test.ts index 9e1354595..359909e7a 100644 --- a/frontend/tests/resetProject.test.ts +++ b/frontend/tests/resetProject.test.ts @@ -59,7 +59,6 @@ test('reset project and upload .zip file', async ({ page, tempProject, tempDir } await resetProjectModel.assertGone(); // Step 4: confirm it's empty now - await page.request.get(`${testEnv.serverBaseUrl}/hg/command/${tempProject.code}/invalidatedircache`); // Force an NFS cache clear const afterResetResponse = await page.request.get(`${testEnv.serverBaseUrl}/hg/${tempProject.code}/file/tip?style=json-lex`); const afterResetJson = await afterResetResponse.json() as HgWebJson; expect(afterResetJson.node).toEqual(allZeroHash); @@ -78,7 +77,6 @@ test('reset project and upload .zip file', async ({ page, tempProject, tempDir } await resetProjectModel.assertGone(); // Step 6: confirm tip hash and contents are same as before reset - await page.request.get(`${testEnv.serverBaseUrl}/hg/command/${tempProject.code}/invalidatedircache`); // Force an NFS cache clear const afterUploadResponse = await page.request.get(`${testEnv.serverBaseUrl}/hg/${tempProject.code}/file/tip?style=json-lex`); const afterResetJSon = await afterUploadResponse.json() as HgWebJson; expect(afterResetJSon).toEqual(beforeResetJson); // NOT .toBe(), which would check that they're the same object.