-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFileBlogSessionStore.cs
More file actions
68 lines (55 loc) · 2.26 KB
/
Copy pathFileBlogSessionStore.cs
File metadata and controls
68 lines (55 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System.Text.Json;
namespace BlogWriter;
/// <summary>Stores each session as a JSON document on the local machine.</summary>
public sealed class FileBlogSessionStore(string directoryPath) : IBlogSessionStore
{
private static readonly JsonSerializerOptions s_jsonOptions = new() { WriteIndented = true };
private readonly string _directoryPath = directoryPath;
public async Task<BlogSession> CreateAsync(ResearchState state, CancellationToken cancellationToken = default)
{
DateTimeOffset now = DateTimeOffset.UtcNow;
var session = new BlogSession
{
Id = Guid.NewGuid().ToString("N"),
CreatedAt = now,
UpdatedAt = now,
State = state,
};
await SaveAsync(session, cancellationToken);
return session;
}
public async Task<BlogSession?> GetAsync(string sessionId, CancellationToken cancellationToken = default)
{
if (!IsValidId(sessionId))
{
return null;
}
string path = GetPath(sessionId);
if (!File.Exists(path))
{
return null;
}
await using FileStream stream = File.OpenRead(path);
return await JsonSerializer.DeserializeAsync<BlogSession>(stream, s_jsonOptions, cancellationToken);
}
public async Task SaveAsync(BlogSession session, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(session);
if (!IsValidId(session.Id))
{
throw new ArgumentException("Session ID must be a 32-character hexadecimal GUID.", nameof(session));
}
Directory.CreateDirectory(_directoryPath);
session.UpdatedAt = DateTimeOffset.UtcNow;
string path = GetPath(session.Id);
string temporaryPath = $"{path}.{Guid.NewGuid():N}.tmp";
await using (FileStream stream = File.Create(temporaryPath))
{
await JsonSerializer.SerializeAsync(stream, session, s_jsonOptions, cancellationToken);
}
File.Move(temporaryPath, path, overwrite: true);
}
private string GetPath(string sessionId) => Path.Combine(_directoryPath, $"{sessionId}.json");
private static bool IsValidId(string sessionId) =>
Guid.TryParseExact(sessionId, "N", out _);
}