Add synced user notes
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user