Families.Web
1.0.0.0
사진, 동영상, 글, 댓글과 반응을 가족끼리만 공유하는 비공개 앨범·타임라인 서비스입니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
JsonPostStore.cs
이 파일의 문서화 페이지로 가기
1
using
System.IO;
2
using
System.Text.Json;
3
using
System.Text.Json.Serialization;
4
using
FamiliesApp.Models
;
5
6
namespace
FamiliesApp.Services
;
7
16
public
sealed
class
JsonPostStore
:
IPostStore
17
{
26
private
readonly
IFamilyTenantStore
_tenants
;
35
private
static
readonly SemaphoreSlim
_gate
=
new
(1, 1);
36
45
private
static
readonly JsonSerializerOptions
_jsonOpts
=
new
()
46
{
47
WriteIndented =
true
,
48
PropertyNameCaseInsensitive =
true
,
49
Converters = {
new
JsonStringEnumConverter() }
50
};
51
68
public
JsonPostStore
(
IFamilyTenantStore
tenants) =>
_tenants
= tenants;
69
94
private
string
PostsDir
(
string
slug) =>
95
Path.Combine(
_tenants
.GetTenantDataPath(slug),
"posts"
);
96
129
private
string
PostPath
(
string
slug,
string
postId) =>
130
Path.Combine(
PostsDir
(slug), $
"{Sanitize(postId)}.json"
);
131
172
public
async Task<PostEntry?>
GetAsync
(
string
slug,
string
postId, CancellationToken ct =
default
)
173
{
174
var path =
PostPath
(slug, postId);
175
if
(!File.Exists(path))
return
null
;
176
177
await
_gate
.WaitAsync(ct).ConfigureAwait(
false
);
178
try
179
{
180
await
using
var fs = File.OpenRead(path);
181
return
await JsonSerializer.DeserializeAsync<
PostEntry
>(fs,
_jsonOpts
, ct).ConfigureAwait(
false
);
182
}
183
finally
{
_gate
.Release(); }
184
}
185
218
public
async Task<IReadOnlyList<PostEntry>>
GetAllAsync
(
string
slug, CancellationToken ct =
default
)
219
{
220
var dir =
PostsDir
(slug);
221
if
(!Directory.Exists(dir))
return
[];
222
223
var list =
new
List<PostEntry>();
224
foreach
(var file
in
Directory.GetFiles(dir,
"*.json"
))
225
{
226
await
_gate
.WaitAsync(ct).ConfigureAwait(
false
);
227
try
228
{
229
await
using
var fs = File.OpenRead(file);
230
var p = await JsonSerializer.DeserializeAsync<
PostEntry
>(fs,
_jsonOpts
, ct).ConfigureAwait(
false
);
231
if
(p !=
null
) list.Add(p);
232
}
233
catch
{
/* 깨진 파일 하나로 전체 목록이 죽지 않도록 */
}
234
finally
{
_gate
.Release(); }
235
}
236
return
list.OrderByDescending(p => p.IsPinned).ThenByDescending(p => p.PostedAt).ToList();
237
}
238
287
public
async Task<(IReadOnlyList<PostEntry> Items,
int
TotalCount)>
GetPageAsync
(
288
string
slug,
int
page,
int
pageSize, CancellationToken ct =
default
)
289
{
290
var all = await
GetAllAsync
(slug, ct).ConfigureAwait(
false
);
291
var items = all.Skip((page - 1) * pageSize).Take(pageSize).ToList();
292
return
(items, all.Count);
293
}
294
335
public
async Task<IReadOnlyList<PostEntry>>
GetByAlbumAsync
(
string
slug,
string
albumId, CancellationToken ct =
default
)
336
{
337
var all = await
GetAllAsync
(slug, ct).ConfigureAwait(
false
);
338
return
all.Where(p => p.AlbumId == albumId).ToList();
339
}
340
397
public
async Task<(IReadOnlyList<PostEntry> Items,
int
TotalCount)>
GetByAlbumPageAsync
(
398
string
slug,
string
albumId,
int
page,
int
pageSize, CancellationToken ct =
default
)
399
{
400
var filtered = await
GetByAlbumAsync
(slug, albumId, ct).ConfigureAwait(
false
);
401
var items = filtered.Skip((page - 1) * pageSize).Take(pageSize).ToList();
402
return
(items, filtered.Count);
403
}
404
445
public
async Task
SaveAsync
(
string
slug,
PostEntry
post, CancellationToken ct =
default
)
446
{
447
var dir =
PostsDir
(slug);
448
Directory.CreateDirectory(dir);
449
Directory.CreateDirectory(Path.Combine(
_tenants
.GetTenantDataPath(slug),
"media"
, post.
Id
));
450
451
var path =
PostPath
(slug, post.
Id
);
452
var tmp = path +
".tmp"
;
453
454
await
_gate
.WaitAsync(ct).ConfigureAwait(
false
);
455
try
456
{
457
await
using
(var fs = File.Create(tmp))
458
await JsonSerializer.SerializeAsync(fs, post,
_jsonOpts
, ct).ConfigureAwait(
false
);
459
460
File.Copy(tmp, path, overwrite:
true
);
461
File.Delete(tmp);
462
}
463
finally
{
_gate
.Release(); }
464
}
465
506
public
Task
DeleteAsync
(
string
slug,
string
postId, CancellationToken ct =
default
)
507
{
508
var path =
PostPath
(slug, postId);
509
if
(File.Exists(path)) File.Delete(path);
510
511
var mediaDir = Path.Combine(
_tenants
.GetTenantDataPath(slug),
"media"
, postId);
512
if
(Directory.Exists(mediaDir)) Directory.Delete(mediaDir, recursive:
true
);
513
514
return
Task.CompletedTask;
515
}
516
541
private
static
string
Sanitize
(
string
id
) =>
542
string
.Concat(
id
.Split(Path.GetInvalidFileNameChars()));
543
}
FamiliesApp.Models
Definition
AlbumInfo.cs:1
FamiliesApp.Services
Definition
FamilyOptions.cs:4
FamiliesApp.Models.PostEntry
Definition
PostEntry.cs:43
FamiliesApp.Models.PostEntry.Id
string Id
Definition
PostEntry.cs:52
FamiliesApp.Services.IFamilyTenantStore
Definition
IFamilyTenantStore.cs:14
FamiliesApp.Services.IPostStore
Definition
IPostStore.cs:14
FamiliesApp.Services.JsonPostStore.GetAsync
async Task< PostEntry?> GetAsync(string slug, string postId, CancellationToken ct=default)
Definition
JsonPostStore.cs:172
FamiliesApp.Services.JsonPostStore.SaveAsync
async Task SaveAsync(string slug, PostEntry post, CancellationToken ct=default)
Definition
JsonPostStore.cs:445
FamiliesApp.Services.JsonPostStore.Sanitize
static string Sanitize(string id)
Definition
JsonPostStore.cs:541
FamiliesApp.Services.JsonPostStore._tenants
readonly IFamilyTenantStore _tenants
Definition
JsonPostStore.cs:26
FamiliesApp.Services.JsonPostStore.JsonPostStore
JsonPostStore(IFamilyTenantStore tenants)
Definition
JsonPostStore.cs:68
FamiliesApp.Services.JsonPostStore.GetByAlbumAsync
async Task< IReadOnlyList< PostEntry > > GetByAlbumAsync(string slug, string albumId, CancellationToken ct=default)
Definition
JsonPostStore.cs:335
FamiliesApp.Services.JsonPostStore.GetPageAsync
async Task<(IReadOnlyList< PostEntry > Items, int TotalCount)> GetPageAsync(string slug, int page, int pageSize, CancellationToken ct=default)
Definition
JsonPostStore.cs:287
FamiliesApp.Services.JsonPostStore.DeleteAsync
Task DeleteAsync(string slug, string postId, CancellationToken ct=default)
Definition
JsonPostStore.cs:506
FamiliesApp.Services.JsonPostStore._jsonOpts
static readonly JsonSerializerOptions _jsonOpts
Definition
JsonPostStore.cs:45
FamiliesApp.Services.JsonPostStore.PostPath
string PostPath(string slug, string postId)
Definition
JsonPostStore.cs:129
FamiliesApp.Services.JsonPostStore.PostsDir
string PostsDir(string slug)
Definition
JsonPostStore.cs:94
FamiliesApp.Services.JsonPostStore._gate
static readonly SemaphoreSlim _gate
Definition
JsonPostStore.cs:35
FamiliesApp.Services.JsonPostStore.GetByAlbumPageAsync
async Task<(IReadOnlyList< PostEntry > Items, int TotalCount)> GetByAlbumPageAsync(string slug, string albumId, int page, int pageSize, CancellationToken ct=default)
Definition
JsonPostStore.cs:397
FamiliesApp.Services.JsonPostStore.GetAllAsync
async Task< IReadOnlyList< PostEntry > > GetAllAsync(string slug, CancellationToken ct=default)
Definition
JsonPostStore.cs:218
Services
JsonPostStore.cs
다음에 의해 생성됨 :
1.17.0