public class FolderEntity : BaseEntity<Guid>
{
public string Name { get; private set; }
public string ExternalId { get; private set; } // Google Drive ID
public Guid ProviderId { get; private set; }
public Guid? ParentFolderId { get; private set; }
public string Description { get; private set; } // Contains AlbumId mapping
public CloudProviderType ProviderType { get; private set; }
}
FileEntity
public class FileEntity : BaseEntity<Guid>
{
public string Name { get; private set; }
public string ExternalId { get; private set; }
public Guid FolderId { get; private set; }
public string MimeType { get; private set; }
public long Size { get; private set; }
public string ThumbnailUrl { get; private set; }
public string WebViewLink { get; private set; }
}
Sync Architecture
Sync Flow
Batch Processing
Photos are synced in batches to optimize performance:
public class StorageConfiguration
{
public const int ItemPerBatch = 50; // Photos per batch
}
Progress Events
public record StorageFolderSyncProgressEvent : IInServiceEvent
{
public required string FolderExternalId { get; set; }
public Guid? AlbumId { get; set; }
public required int ProcessedCount { get; set; }
public required int TotalCount { get; set; }
public required int BatchNumber { get; set; }
public required int TotalBatches { get; set; }
public required bool IsComplete { get; set; }
}
Google Drive Integration
OAuth2 Flow
Supported Operations
Operation
Description
ListFiles
List files in a folder
GetFile
Get file metadata
DownloadFile
Download file content
CreateFolder
Create a new folder
ShareFolder
Generate shareable link
GetThumbnail
Get image thumbnail URL
API Endpoints
Folder Operations
# List folders
GET /api/v1/storage/folders
# Get folder detail
GET /api/v1/storage/folders/{id}
# Sync folder from Google Drive
POST /api/v1/storage/folders/{id}/sync
# Get photos in folder
GET /api/v1/storage/folders/{id}/photos
File Operations
# Get file detail
GET /api/v1/storage/files/{id}
# Get file thumbnail
GET /api/v1/storage/files/{id}/thumbnail
# Get download URL
GET /api/v1/storage/files/{id}/download
Auth Operations
# Initiate OAuth login
POST /api/v1/storage/auth/login
# Handle OAuth callback
POST /api/v1/storage/auth/callback
# Revoke token
POST /api/v1/storage/auth/revoke
Audit Logging
The Storage Service implements comprehensive audit logging using the decorator pattern:
public class AuditedFolderService : IFolderService
{
private readonly IFolderService _folderService;
private readonly IAuditLogService _auditLogService;
public async Task<bool> SyncByIdAsync(CloudProviderType provider, Guid folderId, ...)
{
var stopwatch = Stopwatch.StartNew();
var auditLogId = await _auditLogService.CreateAuditLogAsync(...);
try
{
var result = await _folderService.SyncByIdAsync(provider, folderId, ...);
stopwatch.Stop();
await _auditLogService.MarkCompletedAsync(auditLogId, ..., stopwatch.ElapsedMilliseconds);
return result;
}
catch (Exception ex)
{
stopwatch.Stop();
await _auditLogService.MarkFailedAsync(auditLogId, ex.Message, stopwatch.ElapsedMilliseconds);
throw;
}
}
}
Performance Optimizations
Async Queue Processing
Audit logs are processed asynchronously to avoid blocking sync operations:
public class InternalAuditLogQueueService : IAuditLogService
{
private readonly ConcurrentQueue<AuditLogOperation> _auditLogQueue;
public async Task<AuditLogEntity> CreateAuditLogAsync(...)
{
var operation = new AuditLogOperation { Type = Create, ... };
_auditLogQueue.Enqueue(operation);
return AuditLogEntity.Create(...); // Return immediately
}
}
Caching
Frequently accessed data is cached using Redis:
Folder metadata
File thumbnails URLs
OAuth tokens (encrypted)
Error Handling
Retry Logic
Sync operations use exponential backoff for transient failures: