118 lines
3.3 KiB
Go
118 lines
3.3 KiB
Go
package resource
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"voidraft/internal/models/ent"
|
|
"voidraft/internal/models/ent/document"
|
|
"voidraft/internal/syncer/snapshot"
|
|
)
|
|
|
|
const documentContentBlob = "content.md"
|
|
|
|
// DocumentAdapter 负责文档资源的快照导入导出。
|
|
type DocumentAdapter struct {
|
|
client *ent.Client
|
|
}
|
|
|
|
// NewDocumentAdapter 创建文档适配器。
|
|
func NewDocumentAdapter(client *ent.Client) *DocumentAdapter {
|
|
return &DocumentAdapter{client: client}
|
|
}
|
|
|
|
// Kind 返回适配器负责的资源类型。
|
|
func (a *DocumentAdapter) Kind() string {
|
|
return "documents"
|
|
}
|
|
|
|
// Export 导出文档快照记录。
|
|
func (a *DocumentAdapter) Export(ctx context.Context) ([]snapshot.Record, error) {
|
|
documents, err := a.client.Document.Query().Order(document.ByUUID()).All(exportContext(ctx))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
records := make([]snapshot.Record, 0, len(documents))
|
|
for _, item := range documents {
|
|
values := map[string]interface{}{
|
|
document.FieldUUID: item.UUID,
|
|
document.FieldCreatedAt: item.CreatedAt,
|
|
document.FieldUpdatedAt: item.UpdatedAt,
|
|
document.FieldTitle: item.Title,
|
|
document.FieldLocked: item.Locked,
|
|
}
|
|
if item.DeletedAt != nil {
|
|
values[document.FieldDeletedAt] = *item.DeletedAt
|
|
}
|
|
|
|
record, err := snapshot.NewRecord(a.Kind(), item.UUID, values, map[string][]byte{
|
|
documentContentBlob: []byte(item.Content),
|
|
})
|
|
if err != nil {
|
|
return nil, fmt.Errorf("build document record %s: %w", item.UUID, err)
|
|
}
|
|
records = append(records, record)
|
|
}
|
|
|
|
return records, nil
|
|
}
|
|
|
|
// Apply 将快照记录应用到本地文档表。
|
|
func (a *DocumentAdapter) Apply(ctx context.Context, records []snapshot.Record) error {
|
|
applyCtx := importContext(ctx)
|
|
|
|
for _, record := range records {
|
|
found, err := a.client.Document.Query().Where(document.UUIDEQ(record.ID)).First(applyCtx)
|
|
switch {
|
|
case ent.IsNotFound(err):
|
|
if err := a.create(applyCtx, record); err != nil {
|
|
return err
|
|
}
|
|
case err != nil:
|
|
return err
|
|
default:
|
|
if shouldApplyRecord(found.UpdatedAt, record) {
|
|
if err := a.update(applyCtx, found.ID, record); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// create 创建新的文档记录。
|
|
func (a *DocumentAdapter) create(ctx context.Context, record snapshot.Record) error {
|
|
builder := a.client.Document.Create().
|
|
SetUUID(record.ID).
|
|
SetTitle(stringValue(record, document.FieldTitle)).
|
|
SetContent(blobString(record, documentContentBlob)).
|
|
SetLocked(boolValue(record, document.FieldLocked)).
|
|
SetCreatedAt(stringValue(record, document.FieldCreatedAt)).
|
|
SetUpdatedAt(stringValue(record, document.FieldUpdatedAt))
|
|
|
|
if deletedAt := recordDeletedAtString(record); deletedAt != nil {
|
|
builder.SetDeletedAt(*deletedAt)
|
|
}
|
|
|
|
return builder.Exec(ctx)
|
|
}
|
|
|
|
// update 更新已有文档记录。
|
|
func (a *DocumentAdapter) update(ctx context.Context, id int, record snapshot.Record) error {
|
|
builder := a.client.Document.UpdateOneID(id).
|
|
SetTitle(stringValue(record, document.FieldTitle)).
|
|
SetContent(blobString(record, documentContentBlob)).
|
|
SetLocked(boolValue(record, document.FieldLocked)).
|
|
SetUpdatedAt(stringValue(record, document.FieldUpdatedAt))
|
|
|
|
if deletedAt := recordDeletedAtString(record); deletedAt != nil {
|
|
builder.SetDeletedAt(*deletedAt)
|
|
} else {
|
|
builder.ClearDeletedAt()
|
|
}
|
|
|
|
return builder.Exec(ctx)
|
|
}
|