-
Notifications
You must be signed in to change notification settings - Fork 71
feat: Sort memories chronologically #436
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| using ImmichFrame.Core.Api; | ||
| using ImmichFrame.Core.Exceptions; | ||
| using ImmichFrame.Core.Interfaces; | ||
| using ImmichFrame.Core.Logic.Pool; | ||
|
|
||
| namespace ImmichFrame.Core.Logic; | ||
|
|
||
| public class LogicPoolAdapter(IAssetPool pool, ImmichApi immichApi, string? webhook) : IImmichFrameLogic | ||
| { | ||
| public async Task<AssetResponseDto?> GetNextAsset() | ||
| => (await pool.GetAssets(1)).FirstOrDefault(); | ||
|
|
||
| public Task<IEnumerable<AssetResponseDto>> GetAssets() | ||
| => pool.GetAssets(25); | ||
|
|
||
| public Task<AssetResponseDto> GetAssetInfoById(Guid assetId) | ||
| => immichApi.GetAssetInfoAsync(assetId, null); | ||
|
|
||
| public async Task<IEnumerable<AlbumResponseDto>> GetAlbumInfoById(Guid assetId) | ||
| => await immichApi.GetAllAlbumsAsync(assetId, null); | ||
|
|
||
| public Task<long> GetTotalAssets() => pool.GetAssetCount(); | ||
|
|
||
| public Task SendWebhookNotification(IWebhookNotification notification) => | ||
| WebhookHelper.SendWebhookNotification(notification, webhook); | ||
|
|
||
| public virtual async Task<(string fileName, string ContentType, Stream fileStream)> GetImage(Guid id) | ||
| { | ||
| var data = await immichApi.ViewAssetAsync(id, string.Empty, AssetMediaSize.Preview); | ||
|
|
||
| if (data == null) | ||
| throw new AssetNotFoundException($"Asset {id} was not found!"); | ||
|
|
||
| var contentType = ""; | ||
| if (data.Headers.ContainsKey("Content-Type")) | ||
| { | ||
| contentType = data.Headers["Content-Type"].FirstOrDefault() ?? ""; | ||
| } | ||
|
|
||
| var ext = contentType.ToLower() == "image/webp" ? "webp" : "jpeg"; | ||
| var fileName = $"{id}.{ext}"; | ||
|
|
||
| return (fileName, contentType, data.Stream); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,14 +5,14 @@ | |
|
|
||
| namespace ImmichFrame.Core.Logic.Pool; | ||
|
|
||
| public class MemoryAssetsPool(ImmichApi immichApi, IAccountSettings accountSettings) : CachingApiAssetsPool(new DailyApiCache(), immichApi, accountSettings) | ||
| public class MemoryAssetsPool(ImmichApi immichApi, IAccountSettings accountSettings) : CachingApiAssetsPool(new DailyApiCache(), accountSettings) | ||
| { | ||
| protected override async Task<IEnumerable<AssetResponseDto>> LoadAssets(CancellationToken ct = default) | ||
| protected override async Task<IList<AssetResponseDto>> LoadAssets(CancellationToken ct = default) | ||
| { | ||
| var memories = await immichApi.SearchMemoriesAsync(DateTime.Now, null, null, null, ct); | ||
|
|
||
| var memoryAssets = new List<AssetResponseDto>(); | ||
| foreach (var memory in memories) | ||
| foreach (var memory in memories.OrderBy(m => m.MemoryAt)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainChronological sorting implemented correctly. The addition of However, there's a critical concern raised in the PR comments: JoeRu noted that sorting may be undone by random/shuffle operations in Run the following script to identify potential shuffle operations that might override this sorting: 🏁 Script executed: #!/bin/bash
# Search for random/shuffle operations in the codebase that might affect asset order
echo "=== Checking TotalAccountImagesSelectionStrategy.cs ==="
rg -nC3 -g 'TotalAccountImagesSelectionStrategy.cs' '\b(Random|Shuffle|OrderBy.*Guid\.NewGuid)\b'
echo "=== Checking MultiImmichFrameLogicDelegate.cs ==="
rg -nC3 -g 'MultiImmichFrameLogicDelegate.cs' '\b(Random|Shuffle|OrderBy.*Guid\.NewGuid)\b'
echo "=== Checking for any shuffle operations in Logic/AccountSelection ==="
rg -nC3 -g '*.cs' --type-add 'cs:*.cs' 'Logic/AccountSelection' -e '\b(Random|Shuffle|OrderBy.*Guid\.NewGuid)\b'
echo "=== Checking for any shuffle operations in PooledImmichFrameLogic ==="
rg -nC3 -g 'PooledImmichFrameLogic.cs' '\b(Random|Shuffle|OrderBy.*Guid\.NewGuid)\b'Length of output: 1953 Sorting is negated by downstream shuffle operations.
Reapply 🤖 Prompt for AI Agents |
||
| { | ||
| var assets = memory.Assets.ToList(); | ||
| var yearsAgo = DateTime.Now.Year - memory.Data.Year; | ||
|
|
@@ -25,7 +25,6 @@ protected override async Task<IEnumerable<AssetResponseDto>> LoadAssets(Cancella | |
| asset.ExifInfo = assetInfo.ExifInfo; | ||
| asset.People = assetInfo.People; | ||
| } | ||
|
|
||
| asset.ExifInfo.Description = $"{yearsAgo} {(yearsAgo == 1 ? "year" : "years")} ago"; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thread safety: Concurrent GetAssets calls will corrupt _next.
The
_nextfield is mutated without synchronization (lines 31, 37), so concurrent calls toGetAssetswill race and produce incorrect results or skip assets. If this pool is accessed from multiple threads (e.g., concurrent requests in a web app), the iteration state will be corrupted.Apply thread-local state or locking:
Note: If
AllAssetsperforms async I/O, consider usingSemaphoreSliminstead oflockto avoid blocking threads.🤖 Prompt for AI Agents