Files
2026-07-18 22:22:29 -05:00

67 lines
2.3 KiB
C#

using MongoDB.Driver;
using QuestionsApi.Models;
namespace QuestionsApi.Services;
public sealed record UserNotepadUpdateResult(UserNotepad? Note, UserNotepad? Current)
{
public bool Succeeded => Note is not null;
}
public sealed class UserNotepadStore
{
private readonly IMongoCollection<UserNotepad> _notes;
public UserNotepadStore(MongoDatabaseProvider mongo)
{
_notes = mongo.Database.GetCollection<UserNotepad>("UserNotepads");
_notes.Indexes.CreateOne(new CreateIndexModel<UserNotepad>(
Builders<UserNotepad>.IndexKeys.Ascending(note => note.UserId),
new CreateIndexOptions { Unique = true, Name = "user_notepad_unique_user" }));
}
public async Task<UserNotepad?> GetAsync(string userId) =>
await _notes.Find(note => note.UserId == userId).FirstOrDefaultAsync();
public async Task<UserNotepadUpdateResult> UpdateAsync(
string userId,
string content,
long expectedRevision)
{
var now = DateTime.UtcNow;
if (expectedRevision == 0)
{
var created = new UserNotepad
{
UserId = userId,
Content = content,
Revision = 1,
CreatedUtc = now,
UpdatedUtc = now
};
try
{
await _notes.InsertOneAsync(created);
return new UserNotepadUpdateResult(created, null);
}
catch (MongoWriteException exception) when (
exception.WriteError?.Category == ServerErrorCategory.DuplicateKey)
{
return new UserNotepadUpdateResult(null, await GetAsync(userId));
}
}
var updated = await _notes.FindOneAndUpdateAsync(
note => note.UserId == userId && note.Revision == expectedRevision,
Builders<UserNotepad>.Update
.Set(note => note.Content, content)
.Set(note => note.UpdatedUtc, now)
.Inc(note => note.Revision, 1),
new FindOneAndUpdateOptions<UserNotepad> { ReturnDocument = ReturnDocument.After });
return updated is not null
? new UserNotepadUpdateResult(updated, null)
: new UserNotepadUpdateResult(null, await GetAsync(userId));
}
}