From 34350fdbb33d38dfbaa6251d7d97e6a0f258f967 Mon Sep 17 00:00:00 2001 From: Jason Barden Date: Wed, 27 May 2026 13:32:22 +0100 Subject: [PATCH 1/3] change ct to cancellationToken --- .claude/rules/onedrive-auth.md | 6 +-- .claude/rules/onedrive-background.md | 10 ++--- .claude/rules/onedrive-di.md | 2 +- .claude/rules/onedrive-graph.md | 22 +++++------ .claude/rules/onedrive-onboarding.md | 2 +- .claude/rules/onedrive-persistence.md | 2 +- .claude/rules/onedrive-sync.md | 10 ++--- .../Auth/AuthService.cs | 10 ++--- .../Auth/IAuthService.cs | 6 +-- .../Auth/ITokenCacheService.cs | 2 +- .../Auth/TokenCacheService.cs | 2 +- .../Graph/GraphService.cs | 10 ++--- .../Graph/IGraphService.cs | 2 +- .../Onboarding/AccountOnboardingService.cs | 10 ++--- .../Onboarding/IAccountOnboardingService.cs | 2 +- .../Repositories/AccountRepository.cs | 28 +++++++------- .../Repositories/DriveStateRepository.cs | 14 +++---- .../FileClassificationRuleRepository.cs | 22 +++++------ .../Repositories/IAccountRepository.cs | 8 ++-- .../Repositories/IDriveStateRepository.cs | 4 +- .../IFileClassificationRuleRepository.cs | 6 +-- .../Repositories/ISyncRepository.cs | 10 ++--- .../Repositories/ISyncRuleRepository.cs | 6 +-- .../Repositories/ISyncedItemRepository.cs | 8 ++-- .../Repositories/SyncRepository.cs | 38 +++++++++---------- .../Repositories/SyncRuleRepository.cs | 22 +++++------ .../Repositories/SyncedItemRepository.cs | 28 +++++++------- .../Wizard/AddAccountWizardViewModel.cs | 22 +++++------ .../Workspace/WorkspaceViewModel.cs | 4 +- 29 files changed, 159 insertions(+), 159 deletions(-) diff --git a/.claude/rules/onedrive-auth.md b/.claude/rules/onedrive-auth.md index f0a3015..69808a6 100644 --- a/.claude/rules/onedrive-auth.md +++ b/.claude/rules/onedrive-auth.md @@ -158,8 +158,8 @@ string email = result.ClaimsPrincipal?.FindFirst("preferred_username")?.Value ## IAuthService contract ```csharp -Task> SignInInteractiveAsync(CancellationToken ct = default); -Task> AcquireTokenSilentAsync(string accountId, CancellationToken ct = default); -Task SignOutAsync(string accountId, CancellationToken ct = default); +Task> SignInInteractiveAsync(CancellationToken cancellationToken = default); +Task> AcquireTokenSilentAsync(string accountId, CancellationToken cancellationToken = default); +Task SignOutAsync(string accountId, CancellationToken cancellationToken = default); Task> GetCachedAccountIdsAsync(); ``` diff --git a/.claude/rules/onedrive-background.md b/.claude/rules/onedrive-background.md index c1c278c..276bb69 100644 --- a/.claude/rules/onedrive-background.md +++ b/.claude/rules/onedrive-background.md @@ -24,7 +24,7 @@ Use `Interlocked.Exchange` to prevent concurrent sync passes: ```csharp private long _runningFlag; -private async Task RunSyncPassAsync(CancellationToken ct) +private async Task RunSyncPassAsync(CancellationToken cancellationToken) { if (Interlocked.Exchange(ref _runningFlag, 1) == 1) return; try { /* sync all accounts */ } @@ -76,15 +76,15 @@ event EventHandler? SyncCompleted; void StartSync(TimeSpan? interval = null); void StopSync(); void SetInterval(TimeSpan interval); -Task TriggerNowAsync(CancellationToken ct = default); -Task TriggerAccountAsync(string accountId, CancellationToken ct = default); -Task TriggerAccountAsync(OneDriveAccount account, CancellationToken ct = default); +Task TriggerNowAsync(CancellationToken cancellationToken = default); +Task TriggerAccountAsync(string accountId, CancellationToken cancellationToken = default); +Task TriggerAccountAsync(OneDriveAccount account, CancellationToken cancellationToken = default); Task CancelAccountSyncAsync(string accountId); ``` ## CancellationToken rules -- **Every** public async method takes `CancellationToken ct = default` as the final parameter. +- **Every** public async method takes `CancellationToken cancellationToken = default` as the final parameter. - Propagate `ct` to every downstream `await` — never pass `CancellationToken.None` unless you are deliberately starting unlinked work (e.g. timer-tick root, post-cancellation cleanup). - Catch `OperationCanceledException` at the service boundary only — do not swallow it inside pipeline steps. - Use `CancellationTokenSource.CreateLinkedTokenSource(ct)` when you need per-account cancellation composable with an outer token. diff --git a/.claude/rules/onedrive-di.md b/.claude/rules/onedrive-di.md index f2c422c..32af807 100644 --- a/.claude/rules/onedrive-di.md +++ b/.claude/rules/onedrive-di.md @@ -67,7 +67,7 @@ services.AddDbContextFactory(options => // Repository usage — one context per async operation public class AccountRepository(IDbContextFactory dbFactory) : IAccountRepository { - public async Task> GetByIdAsync(AccountId id, CancellationToken ct) + public async Task> GetByIdAsync(AccountId id, CancellationToken cancellationToken) { await using var context = await dbFactory.CreateDbContextAsync(ct); var entity = await context.Accounts.FindAsync([id], ct); diff --git a/.claude/rules/onedrive-graph.md b/.claude/rules/onedrive-graph.md index 2411e64..064a719 100644 --- a/.claude/rules/onedrive-graph.md +++ b/.claude/rules/onedrive-graph.md @@ -19,7 +19,7 @@ public GraphServiceClient CreateClient(string accessToken) private sealed class StaticAccessTokenProvider(string token) : IAccessTokenProvider { - public Task GetAuthorizationTokenAsync(Uri uri, ..., CancellationToken ct = default) + public Task GetAuthorizationTokenAsync(Uri uri, ..., CancellationToken cancellationToken = default) => Task.FromResult(token); public AllowedHostsValidator AllowedHostsValidator { get; } = new(["graph.microsoft.com"]); @@ -88,7 +88,7 @@ Recursively enumerates a folder subtree. Use a `HashSet` of visited IDs ```csharp static async Task EnumerateSubFolderAsync(GraphServiceClient client, DriveId driveId, string parentId, - string relativePath, List items, HashSet visited, CancellationToken ct) + string relativePath, List items, HashSet visited, CancellationToken cancellationToken) { if (!visited.Add(parentId)) return; // cycle guard @@ -188,15 +188,15 @@ var downloadUrl = ExtractDownloadUrl(item); // Option ## IGraphService contract ```csharp -Task> GetDriveIdAsync(string accountId, string accessToken, CancellationToken ct = default); -Task, GraphError>> GetRootFoldersAsync(string accountId, string accessToken, CancellationToken ct = default); -Task, GraphError>> GetChildFoldersAsync(string accessToken, DriveId driveId, string parentFolderId, CancellationToken ct = default); -Task> GetQuotaAsync(string accountId, string accessToken, CancellationToken ct = default); -Task, GraphError>> EnumerateFolderAsync(string accessToken, DriveId driveId, string folderId, string remotePath, CancellationToken ct = default); -Task> GetFolderIdByPathAsync(string accessToken, DriveId driveId, string remotePath, CancellationToken ct = default); -Task> GetDownloadUrlAsync(string accountId, string accessToken, string itemId, CancellationToken ct = default); -Task> UploadFileAsync(string accountId, string accessToken, string localPath, string remotePath, string parentFolderId, CancellationToken ct = default); -Task> DeleteItemAsync(string accountId, string accessToken, string itemId, CancellationToken ct = default); +Task> GetDriveIdAsync(string accountId, string accessToken, CancellationToken cancellationToken = default); +Task, GraphError>> GetRootFoldersAsync(string accountId, string accessToken, CancellationToken cancellationToken = default); +Task, GraphError>> GetChildFoldersAsync(string accessToken, DriveId driveId, string parentFolderId, CancellationToken cancellationToken = default); +Task> GetQuotaAsync(string accountId, string accessToken, CancellationToken cancellationToken = default); +Task, GraphError>> EnumerateFolderAsync(string accessToken, DriveId driveId, string folderId, string remotePath, CancellationToken cancellationToken = default); +Task> GetFolderIdByPathAsync(string accessToken, DriveId driveId, string remotePath, CancellationToken cancellationToken = default); +Task> GetDownloadUrlAsync(string accountId, string accessToken, string itemId, CancellationToken cancellationToken = default); +Task> UploadFileAsync(string accountId, string accessToken, string localPath, string remotePath, string parentFolderId, CancellationToken cancellationToken = default); +Task> DeleteItemAsync(string accountId, string accessToken, string itemId, CancellationToken cancellationToken = default); void EvictCachedDriveContext(string accountId); ``` diff --git a/.claude/rules/onedrive-onboarding.md b/.claude/rules/onedrive-onboarding.md index e3f4aae..7b97d26 100644 --- a/.claude/rules/onedrive-onboarding.md +++ b/.claude/rules/onedrive-onboarding.md @@ -9,7 +9,7 @@ /// Persists a new account and its initial sync configuration after the wizard completes. /// Returns the finalised with all defaults applied. /// -Task> CompleteOnboardingAsync(OneDriveAccount account, CancellationToken ct = default); +Task> CompleteOnboardingAsync(OneDriveAccount account, CancellationToken cancellationToken = default); ``` ## Responsibilities (in order) diff --git a/.claude/rules/onedrive-persistence.md b/.claude/rules/onedrive-persistence.md index 82dd1c3..50fd28f 100644 --- a/.claude/rules/onedrive-persistence.md +++ b/.claude/rules/onedrive-persistence.md @@ -190,7 +190,7 @@ IFileClassificationRuleRepository / FileClassificationRuleRepository All write methods return `Result`. Catch EF exceptions at the repository: ```csharp -public async Task> UpsertAsync(AccountEntity entity, CancellationToken ct) +public async Task> UpsertAsync(AccountEntity entity, CancellationToken cancellationToken) { try { diff --git a/.claude/rules/onedrive-sync.md b/.claude/rules/onedrive-sync.md index 833e0b0..5310182 100644 --- a/.claude/rules/onedrive-sync.md +++ b/.claude/rules/onedrive-sync.md @@ -90,7 +90,7 @@ After writing the file: A discrete `ISyncedItemRegistrar` handles two registration tasks that occur during the build phase (not job execution): ```csharp -Task RegisterFolderAsync(AccountId accountId, FolderDeltaItem item, string remotePath, string localPath, Dictionary syncedItems, CancellationToken ct); +Task RegisterFolderAsync(AccountId accountId, FolderDeltaItem item, string remotePath, string localPath, Dictionary syncedItems, CancellationToken cancellationToken); ``` - Creates the local directory via `IFileSystem` if it does not exist. @@ -163,7 +163,7 @@ Set `fileSystemInfo.lastModifiedDateTime` from the local file's `LastWriteTimeUt - Returns `Result`. ```csharp -Task> DownloadAsync(string url, string localPath, DateTimeOffset remoteModified, IProgress? progress = null, CancellationToken ct = default); +Task> DownloadAsync(string url, string localPath, DateTimeOffset remoteModified, IProgress? progress = null, CancellationToken cancellationToken = default); ``` ## Conflict detection @@ -216,7 +216,7 @@ record SyncConflict( ```csharp // ISyncPipeline -Task RunAsync(IEnumerable jobs, string accessToken, Action onProgress, Action onJobCompleted, string accountId, int workerCount, CancellationToken ct = default); +Task RunAsync(IEnumerable jobs, string accessToken, Action onProgress, Action onJobCompleted, string accountId, int workerCount, CancellationToken cancellationToken = default); ``` Never hard-code `workerCount` — always pass `account.SyncConfig.WorkerCount`. @@ -228,8 +228,8 @@ event EventHandler? SyncProgressChanged; event EventHandler? JobCompleted; event EventHandler? ConflictDetected; -Task> SyncAccountAsync(OneDriveAccount account, CancellationToken ct = default); -Task> ResolveConflictAsync(SyncConflict conflict, ConflictPolicy policy, CancellationToken ct = default); +Task> SyncAccountAsync(OneDriveAccount account, CancellationToken cancellationToken = default); +Task> ResolveConflictAsync(SyncConflict conflict, ConflictPolicy policy, CancellationToken cancellationToken = default); ``` ## SyncProgressEventArgs diff --git a/src/AStar.Dev.CloudSyncFunctional/Auth/AuthService.cs b/src/AStar.Dev.CloudSyncFunctional/Auth/AuthService.cs index 07c2e20..d37d211 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Auth/AuthService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Auth/AuthService.cs @@ -11,7 +11,7 @@ public sealed partial class AuthService(IPublicClientApplication app, ILogger - public async Task> SignInInteractiveAsync(CancellationToken ct = default) + public async Task> SignInInteractiveAsync(CancellationToken cancellationToken = default) { try { @@ -19,7 +19,7 @@ public async Task> SignInInteractiveAsync(Cancella .AcquireTokenInteractive(Scopes) .WithPrompt(Prompt.SelectAccount) .WithUseEmbeddedWebView(false) - .ExecuteAsync(ct) + .ExecuteAsync(cancellationToken) .ConfigureAwait(false); return new Ok(BuildAuthResult(msalResult)); @@ -45,7 +45,7 @@ public async Task> SignInInteractiveAsync(Cancella } /// - public async Task> AcquireTokenSilentAsync(string accountId, CancellationToken ct = default) + public async Task> AcquireTokenSilentAsync(string accountId, CancellationToken cancellationToken = default) { try { @@ -54,7 +54,7 @@ public async Task> AcquireTokenSilentAsync(string if (account is null) return new Fail(AuthErrorFactory.Failed("Account not found in token cache.")); - var msalResult = await app.AcquireTokenSilent(Scopes, account).ExecuteAsync(ct).ConfigureAwait(false); + var msalResult = await app.AcquireTokenSilent(Scopes, account).ExecuteAsync(cancellationToken).ConfigureAwait(false); return new Ok(BuildAuthResult(msalResult)); } @@ -70,7 +70,7 @@ public async Task> AcquireTokenSilentAsync(string } /// - public async Task SignOutAsync(string accountId, CancellationToken ct = default) + public async Task SignOutAsync(string accountId, CancellationToken cancellationToken = default) { var accounts = await app.GetAccountsAsync().ConfigureAwait(false); var account = accounts.FirstOrDefault(a => a.HomeAccountId?.Identifier == accountId); diff --git a/src/AStar.Dev.CloudSyncFunctional/Auth/IAuthService.cs b/src/AStar.Dev.CloudSyncFunctional/Auth/IAuthService.cs index aa12414..3be4f15 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Auth/IAuthService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Auth/IAuthService.cs @@ -8,19 +8,19 @@ public interface IAuthService /// Opens an interactive browser sign-in and returns the authenticated result. /// Token to cancel the operation. /// An on success, or an on failure. - Task> SignInInteractiveAsync(CancellationToken ct = default); + Task> SignInInteractiveAsync(CancellationToken cancellationToken = default); /// Silently acquires a new access token for an existing cached account. /// The MSAL HomeAccountId identifier. /// Token to cancel the operation. /// An on success, or an on failure. - Task> AcquireTokenSilentAsync(string accountId, CancellationToken ct = default); + Task> AcquireTokenSilentAsync(string accountId, CancellationToken cancellationToken = default); /// Signs out and removes the account from the token cache. /// The MSAL HomeAccountId identifier. /// Token to cancel the operation. /// A task that completes when sign-out is done. - Task SignOutAsync(string accountId, CancellationToken ct = default); + Task SignOutAsync(string accountId, CancellationToken cancellationToken = default); /// Returns the list of account IDs currently in the token cache. /// A read-only list of MSAL HomeAccountId identifiers. diff --git a/src/AStar.Dev.CloudSyncFunctional/Auth/ITokenCacheService.cs b/src/AStar.Dev.CloudSyncFunctional/Auth/ITokenCacheService.cs index fa26a4c..ee96062 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Auth/ITokenCacheService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Auth/ITokenCacheService.cs @@ -9,5 +9,5 @@ public interface ITokenCacheService /// The MSAL application whose token cache is registered. /// Token to cancel the operation. /// A task that completes when registration is done. - Task RegisterAsync(IPublicClientApplication app, CancellationToken ct = default); + Task RegisterAsync(IPublicClientApplication app, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Auth/TokenCacheService.cs b/src/AStar.Dev.CloudSyncFunctional/Auth/TokenCacheService.cs index ecafc16..0346915 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Auth/TokenCacheService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Auth/TokenCacheService.cs @@ -15,7 +15,7 @@ public sealed partial class TokenCacheService(ILogger logger) private static readonly string CacheDir = BuildCacheDir(); /// - public async Task RegisterAsync(IPublicClientApplication app, CancellationToken ct = default) + public async Task RegisterAsync(IPublicClientApplication app, CancellationToken cancellationToken = default) { try { diff --git a/src/AStar.Dev.CloudSyncFunctional/Graph/GraphService.cs b/src/AStar.Dev.CloudSyncFunctional/Graph/GraphService.cs index 4d4f892..af1bfe8 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Graph/GraphService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Graph/GraphService.cs @@ -9,21 +9,21 @@ public sealed partial class GraphService(IGraphClientFactory clientFactory, ILog private static readonly string[] ChildrenSelect = ["id", "name", "folder", "parentReference"]; /// - public async Task, GraphError>> GetRootFoldersAsync(string accountId, string accessToken, CancellationToken ct = default) + public async Task, GraphError>> GetRootFoldersAsync(string accountId, string accessToken, CancellationToken cancellationToken = default) { try { var client = clientFactory.CreateClient(accessToken); - var drive = await client.Me.Drive.GetAsync(cancellationToken: ct).ConfigureAwait(false); + var drive = await client.Me.Drive.GetAsync(cancellationToken: cancellationToken).ConfigureAwait(false); if (drive?.Id is null) return new Fail, GraphError>(GraphErrorFactory.Unexpected("Drive ID was null.")); - var root = await client.Drives[drive.Id].Root.GetAsync(cancellationToken: ct).ConfigureAwait(false); + var root = await client.Drives[drive.Id].Root.GetAsync(cancellationToken: cancellationToken).ConfigureAwait(false); if (root?.Id is null) return new Fail, GraphError>(GraphErrorFactory.Unexpected("Root item ID was null.")); var page = await client.Drives[drive.Id].Items[root.Id].Children - .GetAsync(req => req.QueryParameters.Select = ChildrenSelect, ct) + .GetAsync(req => req.QueryParameters.Select = ChildrenSelect, cancellationToken: cancellationToken) .ConfigureAwait(false); var folders = new List(); @@ -36,7 +36,7 @@ public async Task, GraphError>> GetRootFoldersAsync(str break; page = await client.Drives[drive.Id].Items[root.Id].Children - .WithUrl(page.OdataNextLink).GetAsync(cancellationToken: ct) + .WithUrl(page.OdataNextLink).GetAsync(cancellationToken: cancellationToken) .ConfigureAwait(false); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Graph/IGraphService.cs b/src/AStar.Dev.CloudSyncFunctional/Graph/IGraphService.cs index 99f7465..db6ba85 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Graph/IGraphService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Graph/IGraphService.cs @@ -10,5 +10,5 @@ public interface IGraphService /// The OAuth2 bearer token for Graph API calls. /// Token to cancel the operation. /// A list of root folders, or a on failure. - Task, GraphError>> GetRootFoldersAsync(string accountId, string accessToken, CancellationToken ct = default); + Task, GraphError>> GetRootFoldersAsync(string accountId, string accessToken, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Onboarding/AccountOnboardingService.cs b/src/AStar.Dev.CloudSyncFunctional/Onboarding/AccountOnboardingService.cs index 9fa38a4..ba36745 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Onboarding/AccountOnboardingService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Onboarding/AccountOnboardingService.cs @@ -14,13 +14,13 @@ public sealed partial class AccountOnboardingService(IAccountRepository accountR ..Enumerable.Range(0, 32).Select(i => (char)i)]; /// - public async Task> CompleteOnboardingAsync(OneDriveAccount account, CancellationToken ct = default) + public async Task> CompleteOnboardingAsync(OneDriveAccount account, CancellationToken cancellationToken = default) { account.IsActive = true; var entity = MapToEntity(account); - return await accountRepository.UpsertAsync(entity, ct) - .BindAsync(_ => UpsertSyncRulesAsync(account, ct)) + return await accountRepository.UpsertAsync(entity, cancellationToken) + .BindAsync(_ => UpsertSyncRulesAsync(account, cancellationToken)) .MatchAsync>( _ => { @@ -34,7 +34,7 @@ public async Task> CompleteOnboardingA }); } - private async Task> UpsertSyncRulesAsync(OneDriveAccount account, CancellationToken ct) + private async Task> UpsertSyncRulesAsync(OneDriveAccount account, CancellationToken cancellationToken) { foreach (var folder in account.SelectedFolders) { @@ -46,7 +46,7 @@ private async Task> UpsertSyncRulesAsync(OneDrive RuleType = RuleType.Include }; - var stopResult = await syncRuleRepository.UpsertAsync(rule, ct) + var stopResult = await syncRuleRepository.UpsertAsync(rule, cancellationToken) .MatchAsync?>( _ => null, error => new Fail(error)) diff --git a/src/AStar.Dev.CloudSyncFunctional/Onboarding/IAccountOnboardingService.cs b/src/AStar.Dev.CloudSyncFunctional/Onboarding/IAccountOnboardingService.cs index b863ec4..1fe40cd 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Onboarding/IAccountOnboardingService.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Onboarding/IAccountOnboardingService.cs @@ -10,5 +10,5 @@ public interface IAccountOnboardingService /// The account to onboard. /// Token to cancel the operation. /// The finalised on success, or a on failure. - Task> CompleteOnboardingAsync(OneDriveAccount account, CancellationToken ct = default); + Task> CompleteOnboardingAsync(OneDriveAccount account, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/AccountRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/AccountRepository.cs index de3b0f7..cbb7ed5 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/AccountRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/AccountRepository.cs @@ -10,10 +10,10 @@ namespace AStar.Dev.CloudSyncFunctional.Persistence.Repositories; public sealed class AccountRepository(IDbContextFactory dbFactory) : IAccountRepository { /// - public async Task> GetByIdAsync(AccountId id, CancellationToken ct = default) + public async Task> GetByIdAsync(AccountId id, CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var entity = await context.Accounts.FindAsync([id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var entity = await context.Accounts.FindAsync([id], cancellationToken).ConfigureAwait(false); return entity is null ? new None(PersistenceErrorFactory.Unexpected("Account not found.")) @@ -21,25 +21,25 @@ public async Task> GetByIdAsync(AccountI } /// - public async Task> GetAllAsync(CancellationToken ct = default) + public async Task> GetAllAsync(CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); - return await context.Accounts.AsNoTracking().ToListAsync(ct).ConfigureAwait(false); + return await context.Accounts.AsNoTracking().ToListAsync(cancellationToken).ConfigureAwait(false); } /// - public async Task> UpsertAsync(AccountEntity entity, CancellationToken ct = default) + public async Task> UpsertAsync(AccountEntity entity, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.Accounts.FindAsync([entity.Id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.Accounts.FindAsync([entity.Id], cancellationToken).ConfigureAwait(false); if (existing is null) context.Accounts.Add(entity); else context.Entry(existing).CurrentValues.SetValues(entity); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } @@ -54,16 +54,16 @@ public async Task> UpsertAsync(AccountEntity enti } /// - public async Task> DeleteAsync(AccountId id, CancellationToken ct = default) + public async Task> DeleteAsync(AccountId id, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.Accounts.FindAsync([id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.Accounts.FindAsync([id], cancellationToken).ConfigureAwait(false); if (existing is not null) { context.Accounts.Remove(existing); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } return new Ok(Unit.Default); diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/DriveStateRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/DriveStateRepository.cs index 623e01c..c1a5033 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/DriveStateRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/DriveStateRepository.cs @@ -10,10 +10,10 @@ namespace AStar.Dev.CloudSyncFunctional.Persistence.Repositories; public sealed class DriveStateRepository(IDbContextFactory dbFactory) : IDriveStateRepository { /// - public async Task> GetByAccountAsync(AccountId accountId, CancellationToken ct = default) + public async Task> GetByAccountAsync(AccountId accountId, CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var entity = await context.DriveStates.FindAsync([accountId], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var entity = await context.DriveStates.FindAsync([accountId], cancellationToken).ConfigureAwait(false); return entity is null ? new None(PersistenceErrorFactory.Unexpected("Drive state not found.")) @@ -21,17 +21,17 @@ public async Task> GetByAccountAsync( } /// - public async Task> UpsertAsync(DriveStateEntity entity, CancellationToken ct = default) + public async Task> UpsertAsync(DriveStateEntity entity, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.DriveStates.FindAsync([entity.AccountId], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.DriveStates.FindAsync([entity.AccountId], cancellationToken).ConfigureAwait(false); if (existing is null) context.DriveStates.Add(entity); else context.Entry(existing).CurrentValues.SetValues(entity); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/FileClassificationRuleRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/FileClassificationRuleRepository.cs index 8e98096..3353884 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/FileClassificationRuleRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/FileClassificationRuleRepository.cs @@ -9,25 +9,25 @@ namespace AStar.Dev.CloudSyncFunctional.Persistence.Repositories; public sealed class FileClassificationRuleRepository(IDbContextFactory dbFactory) : IFileClassificationRuleRepository { /// - public async Task> GetAllAsync(CancellationToken ct = default) + public async Task> GetAllAsync(CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); - return await context.FileClassificationRules.AsNoTracking().ToListAsync(ct).ConfigureAwait(false); + return await context.FileClassificationRules.AsNoTracking().ToListAsync(cancellationToken).ConfigureAwait(false); } /// - public async Task> UpsertAsync(FileClassificationRuleEntity entity, CancellationToken ct = default) + public async Task> UpsertAsync(FileClassificationRuleEntity entity, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.FileClassificationRules.FindAsync([entity.Id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.FileClassificationRules.FindAsync([entity.Id], cancellationToken).ConfigureAwait(false); if (existing is null) context.FileClassificationRules.Add(entity); else context.Entry(existing).CurrentValues.SetValues(entity); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } @@ -42,16 +42,16 @@ public async Task> UpsertAsync(FileClassification } /// - public async Task> DeleteAsync(string id, CancellationToken ct = default) + public async Task> DeleteAsync(string id, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.FileClassificationRules.FindAsync([id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.FileClassificationRules.FindAsync([id], cancellationToken).ConfigureAwait(false); if (existing is not null) { context.FileClassificationRules.Remove(existing); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } return new Ok(Unit.Default); diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IAccountRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IAccountRepository.cs index 2173adb..e477c29 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IAccountRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IAccountRepository.cs @@ -12,22 +12,22 @@ public interface IAccountRepository /// The account identifier. /// Cancellation token. /// The account if found, otherwise None. - Task> GetByIdAsync(AccountId id, CancellationToken ct = default); + Task> GetByIdAsync(AccountId id, CancellationToken cancellationToken = default); /// Retrieves all accounts. /// Cancellation token. /// All stored accounts. - Task> GetAllAsync(CancellationToken ct = default); + Task> GetAllAsync(CancellationToken cancellationToken = default); /// Upserts an account. /// The account to upsert. /// Cancellation token. /// Ok on success, Fail on error. - Task> UpsertAsync(AccountEntity entity, CancellationToken ct = default); + Task> UpsertAsync(AccountEntity entity, CancellationToken cancellationToken = default); /// Deletes an account and all its child entities. /// The account identifier. /// Cancellation token. /// Ok on success, Fail on error. - Task> DeleteAsync(AccountId id, CancellationToken ct = default); + Task> DeleteAsync(AccountId id, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IDriveStateRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IDriveStateRepository.cs index c9c3bb6..ee8bd66 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IDriveStateRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IDriveStateRepository.cs @@ -12,11 +12,11 @@ public interface IDriveStateRepository /// The account identifier. /// Cancellation token. /// The drive state if present, otherwise None. - Task> GetByAccountAsync(AccountId accountId, CancellationToken ct = default); + Task> GetByAccountAsync(AccountId accountId, CancellationToken cancellationToken = default); /// Upserts the drive state for an account. /// The drive state to upsert. /// Cancellation token. /// Ok on success, Fail on error. - Task> UpsertAsync(DriveStateEntity entity, CancellationToken ct = default); + Task> UpsertAsync(DriveStateEntity entity, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IFileClassificationRuleRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IFileClassificationRuleRepository.cs index b473737..3194a91 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IFileClassificationRuleRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/IFileClassificationRuleRepository.cs @@ -10,17 +10,17 @@ public interface IFileClassificationRuleRepository /// Retrieves all file classification rules. /// Cancellation token. /// All stored classification rules. - Task> GetAllAsync(CancellationToken ct = default); + Task> GetAllAsync(CancellationToken cancellationToken = default); /// Upserts a file classification rule. /// The rule to upsert. /// Cancellation token. /// Ok on success, Fail on error. - Task> UpsertAsync(FileClassificationRuleEntity entity, CancellationToken ct = default); + Task> UpsertAsync(FileClassificationRuleEntity entity, CancellationToken cancellationToken = default); /// Deletes a file classification rule by identifier. /// The rule identifier. /// Cancellation token. /// Ok on success, Fail on error. - Task> DeleteAsync(string id, CancellationToken ct = default); + Task> DeleteAsync(string id, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRepository.cs index b762176..88fb3c6 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRepository.cs @@ -12,29 +12,29 @@ public interface ISyncRepository /// The account identifier. /// Cancellation token. /// All pending conflicts for the account. - Task> GetPendingConflictsAsync(AccountId accountId, CancellationToken ct = default); + Task> GetPendingConflictsAsync(AccountId accountId, CancellationToken cancellationToken = default); /// Upserts a sync conflict. /// The conflict to upsert. /// Cancellation token. /// Ok on success, Fail on error. - Task> UpsertConflictAsync(SyncConflictEntity entity, CancellationToken ct = default); + Task> UpsertConflictAsync(SyncConflictEntity entity, CancellationToken cancellationToken = default); /// Marks a conflict as resolved. /// The conflict identifier. /// Cancellation token. /// Ok on success, Fail on error. - Task> ResolveConflictAsync(SyncConflictId id, CancellationToken ct = default); + Task> ResolveConflictAsync(SyncConflictId id, CancellationToken cancellationToken = default); /// Upserts a sync job. /// The job to upsert. /// Cancellation token. /// Ok on success, Fail on error. - Task> UpsertJobAsync(SyncJobEntity entity, CancellationToken ct = default); + Task> UpsertJobAsync(SyncJobEntity entity, CancellationToken cancellationToken = default); /// Removes all completed jobs for a given account. /// The account identifier. /// Cancellation token. /// Ok on success, Fail on error. - Task> ClearCompletedJobsAsync(AccountId accountId, CancellationToken ct = default); + Task> ClearCompletedJobsAsync(AccountId accountId, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRuleRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRuleRepository.cs index f63b51f..ad2a8db 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRuleRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncRuleRepository.cs @@ -12,17 +12,17 @@ public interface ISyncRuleRepository /// The account identifier. /// Cancellation token. /// All sync rules for the account. - Task> GetByAccountAsync(AccountId accountId, CancellationToken ct = default); + Task> GetByAccountAsync(AccountId accountId, CancellationToken cancellationToken = default); /// Upserts a sync rule. /// The sync rule to upsert. /// Cancellation token. /// Ok on success, Fail on error. - Task> UpsertAsync(SyncRuleEntity entity, CancellationToken ct = default); + Task> UpsertAsync(SyncRuleEntity entity, CancellationToken cancellationToken = default); /// Deletes a sync rule by identifier. /// The sync rule identifier. /// Cancellation token. /// Ok on success, Fail on error. - Task> DeleteAsync(SyncRuleId id, CancellationToken ct = default); + Task> DeleteAsync(SyncRuleId id, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncedItemRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncedItemRepository.cs index 9819ddd..532a2ae 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncedItemRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/ISyncedItemRepository.cs @@ -12,23 +12,23 @@ public interface ISyncedItemRepository /// The synced item identifier. /// Cancellation token. /// The item if found, otherwise None. - Task> GetByIdAsync(SyncedItemId id, CancellationToken ct = default); + Task> GetByIdAsync(SyncedItemId id, CancellationToken cancellationToken = default); /// Retrieves all synced items for a given account. /// The account identifier. /// Cancellation token. /// All synced items for the account. - Task> GetByAccountAsync(AccountId accountId, CancellationToken ct = default); + Task> GetByAccountAsync(AccountId accountId, CancellationToken cancellationToken = default); /// Upserts a synced item. /// The item to upsert. /// Cancellation token. /// Ok on success, Fail on error. - Task> UpsertAsync(SyncedItemEntity entity, CancellationToken ct = default); + Task> UpsertAsync(SyncedItemEntity entity, CancellationToken cancellationToken = default); /// Deletes a synced item by identifier. /// The item identifier. /// Cancellation token. /// Ok on success, Fail on error. - Task> DeleteAsync(SyncedItemId id, CancellationToken ct = default); + Task> DeleteAsync(SyncedItemId id, CancellationToken cancellationToken = default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRepository.cs index 10a827f..818c550 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRepository.cs @@ -14,29 +14,29 @@ public sealed class SyncRepository(IDbContextFactory dbFactory) : private const string CompletedStatus = "Completed"; /// - public async Task> GetPendingConflictsAsync(AccountId accountId, CancellationToken ct = default) + public async Task> GetPendingConflictsAsync(AccountId accountId, CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); return await context.SyncConflicts .AsNoTracking() .Where(c => c.AccountId == accountId && c.State == PendingState) - .ToListAsync(ct) + .ToListAsync(cancellationToken) .ConfigureAwait(false); } /// - public async Task> UpsertConflictAsync(SyncConflictEntity entity, CancellationToken ct = default) + public async Task> UpsertConflictAsync(SyncConflictEntity entity, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.SyncConflicts.FindAsync([entity.Id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.SyncConflicts.FindAsync([entity.Id], cancellationToken).ConfigureAwait(false); if (existing is null) context.SyncConflicts.Add(entity); else context.Entry(existing).CurrentValues.SetValues(entity); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } @@ -51,16 +51,16 @@ public async Task> UpsertConflictAsync(SyncConfli } /// - public async Task> ResolveConflictAsync(SyncConflictId id, CancellationToken ct = default) + public async Task> ResolveConflictAsync(SyncConflictId id, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.SyncConflicts.FindAsync([id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.SyncConflicts.FindAsync([id], cancellationToken).ConfigureAwait(false); if (existing is not null) { existing.State = ResolvedState; - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } return new Ok(Unit.Default); @@ -76,17 +76,17 @@ public async Task> ResolveConflictAsync(SyncConfl } /// - public async Task> UpsertJobAsync(SyncJobEntity entity, CancellationToken ct = default) + public async Task> UpsertJobAsync(SyncJobEntity entity, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.SyncJobs.FindAsync([entity.Id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.SyncJobs.FindAsync([entity.Id], cancellationToken).ConfigureAwait(false); if (existing is null) context.SyncJobs.Add(entity); else context.Entry(existing).CurrentValues.SetValues(entity); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } @@ -101,17 +101,17 @@ public async Task> UpsertJobAsync(SyncJobEntity e } /// - public async Task> ClearCompletedJobsAsync(AccountId accountId, CancellationToken ct = default) + public async Task> ClearCompletedJobsAsync(AccountId accountId, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); var completed = await context.SyncJobs .Where(j => j.AccountId == accountId && j.Status == CompletedStatus) - .ToListAsync(ct) + .ToListAsync(cancellationToken) .ConfigureAwait(false); context.SyncJobs.RemoveRange(completed); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRuleRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRuleRepository.cs index 77a858d..497343b 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRuleRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncRuleRepository.cs @@ -10,29 +10,29 @@ namespace AStar.Dev.CloudSyncFunctional.Persistence.Repositories; public sealed class SyncRuleRepository(IDbContextFactory dbFactory) : ISyncRuleRepository { /// - public async Task> GetByAccountAsync(AccountId accountId, CancellationToken ct = default) + public async Task> GetByAccountAsync(AccountId accountId, CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); return await context.SyncRules .AsNoTracking() .Where(r => r.AccountId == accountId) - .ToListAsync(ct) + .ToListAsync(cancellationToken) .ConfigureAwait(false); } /// - public async Task> UpsertAsync(SyncRuleEntity entity, CancellationToken ct = default) + public async Task> UpsertAsync(SyncRuleEntity entity, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.SyncRules.FindAsync([entity.Id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.SyncRules.FindAsync([entity.Id], cancellationToken).ConfigureAwait(false); if (existing is null) context.SyncRules.Add(entity); else context.Entry(existing).CurrentValues.SetValues(entity); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } @@ -47,16 +47,16 @@ public async Task> UpsertAsync(SyncRuleEntity ent } /// - public async Task> DeleteAsync(SyncRuleId id, CancellationToken ct = default) + public async Task> DeleteAsync(SyncRuleId id, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.SyncRules.FindAsync([id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.SyncRules.FindAsync([id], cancellationToken).ConfigureAwait(false); if (existing is not null) { context.SyncRules.Remove(existing); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } return new Ok(Unit.Default); diff --git a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncedItemRepository.cs b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncedItemRepository.cs index 7e92af2..44372b9 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncedItemRepository.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Persistence/Repositories/SyncedItemRepository.cs @@ -10,10 +10,10 @@ namespace AStar.Dev.CloudSyncFunctional.Persistence.Repositories; public sealed class SyncedItemRepository(IDbContextFactory dbFactory) : ISyncedItemRepository { /// - public async Task> GetByIdAsync(SyncedItemId id, CancellationToken ct = default) + public async Task> GetByIdAsync(SyncedItemId id, CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var entity = await context.SyncedItems.FindAsync([id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var entity = await context.SyncedItems.FindAsync([id], cancellationToken).ConfigureAwait(false); return entity is null ? new None(PersistenceErrorFactory.Unexpected("Synced item not found.")) @@ -21,29 +21,29 @@ public async Task> GetByIdAsync(Synce } /// - public async Task> GetByAccountAsync(AccountId accountId, CancellationToken ct = default) + public async Task> GetByAccountAsync(AccountId accountId, CancellationToken cancellationToken = default) { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); return await context.SyncedItems .AsNoTracking() .Where(i => i.AccountId == accountId) - .ToListAsync(ct) + .ToListAsync(cancellationToken) .ConfigureAwait(false); } /// - public async Task> UpsertAsync(SyncedItemEntity entity, CancellationToken ct = default) + public async Task> UpsertAsync(SyncedItemEntity entity, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.SyncedItems.FindAsync([entity.Id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.SyncedItems.FindAsync([entity.Id], cancellationToken).ConfigureAwait(false); if (existing is null) context.SyncedItems.Add(entity); else context.Entry(existing).CurrentValues.SetValues(entity); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); return new Ok(Unit.Default); } @@ -58,16 +58,16 @@ public async Task> UpsertAsync(SyncedItemEntity e } /// - public async Task> DeleteAsync(SyncedItemId id, CancellationToken ct = default) + public async Task> DeleteAsync(SyncedItemId id, CancellationToken cancellationToken = default) { try { - await using var context = await dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false); - var existing = await context.SyncedItems.FindAsync([id], ct).ConfigureAwait(false); + await using var context = await dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); + var existing = await context.SyncedItems.FindAsync([id], cancellationToken).ConfigureAwait(false); if (existing is not null) { context.SyncedItems.Remove(existing); - await context.SaveChangesAsync(ct).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); } return new Ok(Unit.Default); diff --git a/src/AStar.Dev.CloudSyncFunctional/Wizard/AddAccountWizardViewModel.cs b/src/AStar.Dev.CloudSyncFunctional/Wizard/AddAccountWizardViewModel.cs index 3e67b91..c21838d 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Wizard/AddAccountWizardViewModel.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Wizard/AddAccountWizardViewModel.cs @@ -147,10 +147,10 @@ public AddAccountWizardViewModel(IAuthService authService, IGraphService graphSe var canSignIn = this.WhenAnyValue(x => x.IsWaitingForAuth, waiting => !waiting); - SelectProvider = ReactiveCommand.CreateFromTask((kind, ct) => ExecuteSelectProviderAsync(kind, ct)); - SignIn = ReactiveCommand.CreateFromTask(ct => ExecuteSignInAsync(ct), canSignIn); + SelectProvider = ReactiveCommand.CreateFromTask(ExecuteSelectProviderAsync); + SignIn = ReactiveCommand.CreateFromTask(ExecuteSignInAsync, canSignIn); Back = ReactiveCommand.Create(ExecuteBack); - AddAccount = ReactiveCommand.CreateFromTask(ct => ExecuteAddAccountAsync(ct)); + AddAccount = ReactiveCommand.CreateFromTask(ExecuteAddAccountAsync); Cancel = ReactiveCommand.CreateFromTask(ExecuteCancelAsync); } @@ -165,7 +165,7 @@ public void Dispose() /// The account to pass with the event. internal void SimulateCompleted(OneDriveAccount account) => Completed?.Invoke(this, account); - private async Task ExecuteSelectProviderAsync(ProviderKind kind, CancellationToken ct = default) + private async Task ExecuteSelectProviderAsync(ProviderKind kind, CancellationToken cancellationToken = default) { ShowNotImplemented = false; NotImplementedMessage = string.Empty; @@ -183,10 +183,10 @@ private async Task ExecuteSelectProviderAsync(ProviderKind kind, Cancell return RxUnit.Default; } - private async Task ExecuteSignInAsync(CancellationToken ct) + private async Task ExecuteSignInAsync(CancellationToken cancellationToken) { _authCts?.Dispose(); - _authCts = CancellationTokenSource.CreateLinkedTokenSource(ct); + _authCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(60)); using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_authCts.Token, timeoutCts.Token); @@ -227,10 +227,10 @@ await _authService.SignInInteractiveAsync(linkedCts.Token) }); } - private async Task LoadFoldersAsync(AuthResult authResult, CancellationToken ct) + private async Task LoadFoldersAsync(AuthResult authResult, CancellationToken cancellationToken) { IsLoadingFolders = true; - await _graphService.GetRootFoldersAsync(authResult.AccountId, authResult.AccessToken, ct) + await _graphService.GetRootFoldersAsync(authResult.AccountId, authResult.AccessToken, cancellationToken) .MatchAsync( folders => { @@ -266,7 +266,7 @@ private void ExecuteBack() }; } - private async Task ExecuteAddAccountAsync(CancellationToken ct) + private async Task ExecuteAddAccountAsync(CancellationToken cancellationToken) { if (_authResult is null) return; @@ -278,7 +278,7 @@ private async Task ExecuteAddAccountAsync(CancellationToken ct) SelectedFolders = Folders.Where(f => f.IsSelected).Select(f => new SelectedFolder(f.FolderId, f.Name)).ToList() }; - await _onboardingService.CompleteOnboardingAsync(account, ct) + await _onboardingService.CompleteOnboardingAsync(account, cancellationToken) .MatchAsync( finalAccount => Completed?.Invoke(this, finalAccount), error => @@ -288,7 +288,7 @@ await _onboardingService.CompleteOnboardingAsync(account, ct) }); } - private Task ExecuteCancelAsync(CancellationToken ct = default) + private Task ExecuteCancelAsync(CancellationToken cancellationToken = default) { _authCts?.Cancel(); Cancelled?.Invoke(this, EventArgs.Empty); diff --git a/src/AStar.Dev.CloudSyncFunctional/Workspace/WorkspaceViewModel.cs b/src/AStar.Dev.CloudSyncFunctional/Workspace/WorkspaceViewModel.cs index d3f2f39..61f9f37 100644 --- a/src/AStar.Dev.CloudSyncFunctional/Workspace/WorkspaceViewModel.cs +++ b/src/AStar.Dev.CloudSyncFunctional/Workspace/WorkspaceViewModel.cs @@ -88,12 +88,12 @@ public WorkspaceViewModel(IServiceProvider serviceProvider, IAccountRepository a /// Loads persisted accounts from the database and populates . /// Cancellation token. /// A task that completes when accounts are loaded and added to the collection. - public async Task LoadPersistedAccountsAsync(CancellationToken ct = default) + public async Task LoadPersistedAccountsAsync(CancellationToken cancellationToken = default) { if (_accountRepository is null) return; - var entities = await _accountRepository.GetAllAsync(ct); + var entities = await _accountRepository.GetAllAsync(cancellationToken); foreach (var vm in entities.Select(MapToViewModel)) Accounts.Add(vm); if (Accounts.Count > 0 && SelectedAccount is null) From 9937691069c5f78b09c34b587010035e5c46447e Mon Sep 17 00:00:00 2001 From: Jason Barden Date: Wed, 27 May 2026 22:30:53 +0100 Subject: [PATCH 2/3] small tweaks to a few files not 100% related to the actual change --- .gitignore | 3 +++ .vscode/settings.json | 12 ++++++++- .../AStar.Dev.CloudSyncFunctional.csproj | 25 +++++++++--------- .../App.axaml.cs | 2 +- .../Assets/astar.png | Bin 0 -> 15984 bytes .../MainWindow.axaml | 3 ++- 6 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 src/AStar.Dev.CloudSyncFunctional/Assets/astar.png diff --git a/.gitignore b/.gitignore index 378a541..98c206c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,9 @@ mono_crash.* # graphify graphify-out/ +# JetBrains Rider +.idea/ + # Build results [Dd]ebug/ [Dd]ebugPublic/ diff --git a/.vscode/settings.json b/.vscode/settings.json index fc8800f..af4e2d4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,9 +6,19 @@ }, "dotnet.defaultSolution": "AStar.Dev.OneDrive.Functional.slnx", "cSpell.words": [ + "appsettings", + "astar", "Avalonia", + "buildtransitive", + "centralise", + "cloudsync", + "contentfiles", "googledrive", + "Lucide", + "MSAL", "MVVM", - "onedrive" + "onedrive", + "Serilog", + "Testably" ] } \ No newline at end of file diff --git a/src/AStar.Dev.CloudSyncFunctional/AStar.Dev.CloudSyncFunctional.csproj b/src/AStar.Dev.CloudSyncFunctional/AStar.Dev.CloudSyncFunctional.csproj index 03230c3..b6312af 100644 --- a/src/AStar.Dev.CloudSyncFunctional/AStar.Dev.CloudSyncFunctional.csproj +++ b/src/AStar.Dev.CloudSyncFunctional/AStar.Dev.CloudSyncFunctional.csproj @@ -23,18 +23,18 @@ None All - - - - - - - - - - - - + + + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -42,6 +42,7 @@ + diff --git a/src/AStar.Dev.CloudSyncFunctional/App.axaml.cs b/src/AStar.Dev.CloudSyncFunctional/App.axaml.cs index 8b80004..570e764 100644 --- a/src/AStar.Dev.CloudSyncFunctional/App.axaml.cs +++ b/src/AStar.Dev.CloudSyncFunctional/App.axaml.cs @@ -56,7 +56,7 @@ private static void ConfigureServices(IServiceCollection services, IConfiguratio var clientId = configuration["MicrosoftIdentity:ClientId"] ?? throw new InvalidOperationException("MicrosoftIdentity:ClientId is not configured. Set it in appsettings.json or user secrets."); - services.AddSingleton(_ => + services.AddSingleton(_ => PublicClientApplicationBuilder .Create(clientId) .WithAuthority("https://login.microsoftonline.com/consumers") diff --git a/src/AStar.Dev.CloudSyncFunctional/Assets/astar.png b/src/AStar.Dev.CloudSyncFunctional/Assets/astar.png new file mode 100644 index 0000000000000000000000000000000000000000..74b197eaae17c8a9d66b29d6259ce99af25741e6 GIT binary patch literal 15984 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 literal 0 HcmV?d00001 diff --git a/src/AStar.Dev.CloudSyncFunctional/MainWindow.axaml b/src/AStar.Dev.CloudSyncFunctional/MainWindow.axaml index 9b173d9..208e037 100644 --- a/src/AStar.Dev.CloudSyncFunctional/MainWindow.axaml +++ b/src/AStar.Dev.CloudSyncFunctional/MainWindow.axaml @@ -15,6 +15,7 @@ Width="1280" Height="820" MinWidth="960" MinHeight="600" ExtendClientAreaToDecorationsHint="True" + Icon="avares://AStar.Dev.CloudSyncFunctional/Assets/astar.png" Background="{DynamicResource Chrome}"> @@ -219,7 +220,7 @@ Padding="14,8">