67 lines
2.3 KiB
C#
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));
|
|
}
|
|
}
|