Skip to content

fix conv file mongo doc id and add time#1300

Merged
iceljc merged 1 commit intoSciSharp:masterfrom
iceljc:master
Feb 28, 2026
Merged

fix conv file mongo doc id and add time#1300
iceljc merged 1 commit intoSciSharp:masterfrom
iceljc:master

Conversation

@iceljc
Copy link
Collaborator

@iceljc iceljc commented Feb 28, 2026

No description provided.

@qodo-code-review
Copy link

Review Summary by Qodo

Add timestamps and fix MongoDB document ID handling in ConversationFile

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add timestamp tracking with CreatedTime and UpdatedTime properties
• Add JSON property name mappings for MongoDB document serialization
• Fix MongoDB upsert logic to properly handle document ID and timestamps
• Refactor bulk write operations to use update model instead of replace
Diagram
flowchart LR
  A["ConversationFile Model"] -->|"Add timestamps & JSON mappings"| B["Updated Model"]
  C["ConversationFileDocument"] -->|"Add timestamp fields"| D["Enhanced Document"]
  E["SaveConversationFiles"] -->|"Use UpdateOneModel with SetOnInsert"| F["Fixed Upsert Logic"]
  B --> F
  D --> F
Loading

Grey Divider

File Changes

1. src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs ✨ Enhancement +10/-0

Add timestamps and JSON property mappings

• Add JsonPropertyName attributes for proper JSON serialization mapping
• Add CreatedTime property with UTC now default value
• Add UpdatedTime property with UTC now default value
• Add JsonIgnore attribute to Thumbnail property for null handling

src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs


2. src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationFileDocument.cs ✨ Enhancement +8/-2

Add timestamp fields to MongoDB document model

• Add CreatedTime and UpdatedTime datetime properties to document model
• Update ToDomainModel mapping to include new timestamp fields
• Update ToMongoModel mapping to include new timestamp fields

src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationFileDocument.cs


3. src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs 🐞 Bug fix +21/-14

Fix MongoDB upsert logic with proper timestamp handling

• Replace ReplaceOneModel with UpdateOneModel for safer upsert operations
• Add SetOnInsert operations to set document ID and conversation ID only on insert
• Add SetOnInsert for CreatedTime to preserve original creation time
• Update UpdatedTime on every operation to track modifications

src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Feb 28, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. File conv_files.json break 🐞 Bug ✓ Correctness
Description
Adding JsonPropertyName("conversation_id") makes ConversationId no longer deserialize from existing
file-based conv_files.json that likely used "conversationId" (camelCase), causing thumbnails to not
load (ConversationId becomes null/unmatched). This will silently affect any deployment with existing
stored thumbnails in the FileRepository backend.
Code

src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs[R5-6]

+    [JsonPropertyName("conversation_id")]
    public string ConversationId { get; set; }
Evidence
ConversationFile now requires JSON key "conversation_id". FileRepository reads/writes
conv_files.json using JsonSerializer.Deserialize<ConversationFile>(..., _options), and those options
are camelCase; previously, without JsonPropertyName, the stored key would be "conversationId". The
OpenAPI controller matches thumbnails by ConversationFile.ConversationId, so a missing
ConversationId results in no thumbnail match.

src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs[3-16]
src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs[75-82]
src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs[926-933]
src/Infrastructure/BotSharp.OpenAPI/Controllers/Conversation/ConversationController.cs[71-88]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`ConversationFile.ConversationId` is now bound to JSON key `conversation_id`. Existing `conv_files.json` written by the file repository (camelCase `conversationId`) will no longer populate `ConversationId`, so thumbnails won’t match conversations.

## Issue Context
FileRepository reads `conv_files.json` via `JsonSerializer.Deserialize&lt;ConversationFile&gt;(..., _options)` and `_options` uses camelCase naming.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs[3-16]
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs[892-942]
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs[75-82]

## Suggested fix
- Implement backward-compatible parsing in `FileRepository.GetConversationFiles`:
 - Parse JSON into `JsonDocument`.
 - Read `conversation_id` **or** `conversationId`.
 - Read `created_time`/`createdTime` and `updated_time`/`updatedTime` if present.
 - Construct `ConversationFile` manually.
- Optionally, after successful legacy read, rewrite the file in the new format to migrate data.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. File timestamps reset 🐞 Bug ✓ Correctness
Description
FileRepository.SaveConversationFiles writes whatever timestamps are on the provided
ConversationFile; since controller constructs a new ConversationFile per update,
CreatedTime/UpdatedTime default to UtcNow and CreatedTime will reset on every thumbnail update
(UpdatedTime isn’t explicitly bumped). This makes the new time fields unreliable in file-backed
deployments.
Code

src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs[R12-16]

+    [JsonPropertyName("created_time")]
+    public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
+
+    [JsonPropertyName("updated_time")]
+    public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
Evidence
ConversationFile initializes CreatedTime/UpdatedTime to UtcNow at object creation. The thumbnail
endpoint constructs a new instance without preserving prior timestamps.
FileRepository.SaveConversationFiles then serializes that instance directly, overwriting any stored
timestamps and effectively resetting CreatedTime on each update.

src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs[12-16]
src/Infrastructure/BotSharp.OpenAPI/Controllers/Conversation/ConversationController.File.cs[128-136]
src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs[955-971]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
File-backed `conv_files.json` timestamps are not managed: updates overwrite `CreatedTime` because the controller creates a fresh `ConversationFile` and `FileRepository.SaveConversationFiles` writes it directly.

## Issue Context
Mongo backend uses `SetOnInsert` for `CreatedTime` and `Set` for `UpdatedTime`, but FileRepository has no equivalent logic.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs[944-980]
- src/Infrastructure/BotSharp.OpenAPI/Controllers/Conversation/ConversationController.File.cs[119-138]

## Suggested fix
- In `FileRepository.SaveConversationFiles`:
 - If `conv_files.json` exists, load the existing `ConversationFile` (using backward-compatible parsing if needed).
 - Set `file.CreatedTime = existing.CreatedTime` when existing has a non-default value.
 - Set `file.UpdatedTime = DateTime.UtcNow` on every save.
 - If file is new/legacy without times: set `CreatedTime` once and `UpdatedTime` to now.
- Consider also setting timestamps in the controller, but repository-side is safer/centralized.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Mongo CreatedTime not backfilled 🐞 Bug ⛯ Reliability
Description
Mongo upsert sets CreatedTime only on insert; legacy ConversationFiles documents (created before
these fields existed) will keep CreatedTime missing/default and ToDomainModel will return
DateTime.MinValue. If timestamps are displayed or later used for sorting/filtering, this will cause
incorrect behavior.
Code

src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs[R811-816]

+                               var updateBuilder = Builders<ConversationFileDocument>.Update
+                                   .Set(y => y.Thumbnail, file.Thumbnail)
+                                   .Set(y => y.UpdatedTime, DateTime.UtcNow)
+                                   .SetOnInsert(y => y.Id, Guid.NewGuid().ToString())
+                                   .SetOnInsert(y => y.ConversationId, file.ConversationId)
+                                   .SetOnInsert(y => y.CreatedTime, DateTime.UtcNow);
Evidence
ConversationFileDocument now has non-nullable CreatedTime/UpdatedTime and the domain mapping assigns
them directly. The Mongo save path only sets CreatedTime via SetOnInsert, so it will never populate
CreatedTime for pre-existing records that lack the field (or have default values).

src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationFileDocument.cs[5-20]
src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs[811-816]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Legacy `ConversationFiles` MongoDB documents may not have `CreatedTime`. Current upsert only sets it on insert and mapping returns `default(DateTime)` for missing fields.

## Issue Context
New schema introduces `CreatedTime`/`UpdatedTime` in `ConversationFileDocument` and maps them directly into the domain model.

## Fix Focus Areas
- src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationFileDocument.cs[5-31]
- src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs[798-833]

## Suggested fix options
- Option A (recommended): migration/backfill
 - Run an update across the collection to set `CreatedTime` for documents where it is missing (and optionally set `UpdatedTime` if missing).
- Option B: resilient mapping
 - In `ToDomainModel`, if `model.CreatedTime == default`, use `model.UpdatedTime` (if non-default) else `DateTime.UtcNow`.
- Option C: update pipeline
 - Use a MongoDB update pipeline with `$set: { createdTime: { $ifNull: [&quot;$createdTime&quot;, &lt;now&gt;] } }` when updating by `ConversationId`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +5 to 6
[JsonPropertyName("conversation_id")]
public string ConversationId { get; set; }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. File conv_files.json break 🐞 Bug ✓ Correctness

Adding JsonPropertyName("conversation_id") makes ConversationId no longer deserialize from existing
file-based conv_files.json that likely used "conversationId" (camelCase), causing thumbnails to not
load (ConversationId becomes null/unmatched). This will silently affect any deployment with existing
stored thumbnails in the FileRepository backend.
Agent Prompt
## Issue description
`ConversationFile.ConversationId` is now bound to JSON key `conversation_id`. Existing `conv_files.json` written by the file repository (camelCase `conversationId`) will no longer populate `ConversationId`, so thumbnails won’t match conversations.

## Issue Context
FileRepository reads `conv_files.json` via `JsonSerializer.Deserialize<ConversationFile>(..., _options)` and `_options` uses camelCase naming.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Abstraction/Conversations/Models/ConversationFile.cs[3-16]
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs[892-942]
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.cs[75-82]

## Suggested fix
- Implement backward-compatible parsing in `FileRepository.GetConversationFiles`:
  - Parse JSON into `JsonDocument`.
  - Read `conversation_id` **or** `conversationId`.
  - Read `created_time`/`createdTime` and `updated_time`/`updatedTime` if present.
  - Construct `ConversationFile` manually.
- Optionally, after successful legacy read, rewrite the file in the new format to migrate data.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +12 to +16
[JsonPropertyName("created_time")]
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;

[JsonPropertyName("updated_time")]
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. File timestamps reset 🐞 Bug ✓ Correctness

FileRepository.SaveConversationFiles writes whatever timestamps are on the provided
ConversationFile; since controller constructs a new ConversationFile per update,
CreatedTime/UpdatedTime default to UtcNow and CreatedTime will reset on every thumbnail update
(UpdatedTime isn’t explicitly bumped). This makes the new time fields unreliable in file-backed
deployments.
Agent Prompt
## Issue description
File-backed `conv_files.json` timestamps are not managed: updates overwrite `CreatedTime` because the controller creates a fresh `ConversationFile` and `FileRepository.SaveConversationFiles` writes it directly.

## Issue Context
Mongo backend uses `SetOnInsert` for `CreatedTime` and `Set` for `UpdatedTime`, but FileRepository has no equivalent logic.

## Fix Focus Areas
- src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs[944-980]
- src/Infrastructure/BotSharp.OpenAPI/Controllers/Conversation/ConversationController.File.cs[119-138]

## Suggested fix
- In `FileRepository.SaveConversationFiles`:
  - If `conv_files.json` exists, load the existing `ConversationFile` (using backward-compatible parsing if needed).
  - Set `file.CreatedTime = existing.CreatedTime` when existing has a non-default value.
  - Set `file.UpdatedTime = DateTime.UtcNow` on every save.
  - If file is new/legacy without times: set `CreatedTime` once and `UpdatedTime` to now.
- Consider also setting timestamps in the controller, but repository-side is safer/centralized.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@iceljc iceljc merged commit e632f96 into SciSharp:master Feb 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant