Move OpenGraph property generation to models (#52)
- Add auto-OpenGraph field to web log - Only generate properties for posts/pages without them if this flag is set - Set flag to yes on v3 database migration - Add JSON converter for OpenGraph type - Add tests for models
This commit is contained in:
@@ -12,24 +12,24 @@ open NodaTime
|
||||
|
||||
/// SQLite myWebLog data implementation
|
||||
type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSerializer) =
|
||||
|
||||
|
||||
/// Create tables (and their associated indexes) if they do not exist
|
||||
let ensureTables () = backgroundTask {
|
||||
|
||||
|
||||
Configuration.useSerializer (Utils.createDocumentSerializer ser)
|
||||
|
||||
|
||||
let! tables = conn.customList "SELECT name FROM sqlite_master WHERE type = 'table'" [] _.GetString(0)
|
||||
|
||||
|
||||
let needsTable table =
|
||||
not (List.contains table tables)
|
||||
|
||||
|
||||
let creatingTable = "Creating {Table} table..."
|
||||
|
||||
|
||||
// Theme tables
|
||||
if needsTable Table.Theme then
|
||||
log.LogInformation(creatingTable, Table.Theme)
|
||||
do! conn.ensureTable Table.Theme
|
||||
|
||||
|
||||
if needsTable Table.ThemeAsset then
|
||||
log.LogInformation(creatingTable, Table.ThemeAsset)
|
||||
do! conn.customNonQuery
|
||||
@@ -39,32 +39,32 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
updated_on TEXT NOT NULL,
|
||||
data BLOB NOT NULL,
|
||||
PRIMARY KEY (theme_id, path))" []
|
||||
|
||||
|
||||
// Web log table
|
||||
if needsTable Table.WebLog then
|
||||
log.LogInformation(creatingTable, Table.WebLog)
|
||||
do! conn.ensureTable Table.WebLog
|
||||
|
||||
|
||||
// Category table
|
||||
if needsTable Table.Category then
|
||||
log.LogInformation(creatingTable, Table.Category)
|
||||
do! conn.ensureTable Table.Category
|
||||
do! conn.ensureFieldIndex Table.Category "web_log" [ nameof Category.Empty.WebLogId ]
|
||||
|
||||
|
||||
// Web log user table
|
||||
if needsTable Table.WebLogUser then
|
||||
log.LogInformation(creatingTable, Table.WebLogUser)
|
||||
do! conn.ensureTable Table.WebLogUser
|
||||
do! conn.ensureFieldIndex
|
||||
Table.WebLogUser "email" [ nameof WebLogUser.Empty.WebLogId; nameof WebLogUser.Empty.Email ]
|
||||
|
||||
|
||||
// Page tables
|
||||
if needsTable Table.Page then
|
||||
log.LogInformation(creatingTable, Table.Page)
|
||||
do! conn.ensureTable Table.Page
|
||||
do! conn.ensureFieldIndex Table.Page "author" [ nameof Page.Empty.AuthorId ]
|
||||
do! conn.ensureFieldIndex Table.Page "permalink" [ nameof Page.Empty.WebLogId; nameof Page.Empty.Permalink ]
|
||||
|
||||
|
||||
if needsTable Table.PageRevision then
|
||||
log.LogInformation(creatingTable, Table.PageRevision)
|
||||
do! conn.customNonQuery
|
||||
@@ -73,7 +73,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
as_of TEXT NOT NULL,
|
||||
revision_text TEXT NOT NULL,
|
||||
PRIMARY KEY (page_id, as_of))" []
|
||||
|
||||
|
||||
// Post tables
|
||||
if needsTable Table.Post then
|
||||
log.LogInformation(creatingTable, Table.Post)
|
||||
@@ -85,7 +85,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
"status"
|
||||
[ nameof Post.Empty.WebLogId; nameof Post.Empty.Status; nameof Post.Empty.UpdatedOn ]
|
||||
// TODO: index categories by post?
|
||||
|
||||
|
||||
if needsTable Table.PostRevision then
|
||||
log.LogInformation(creatingTable, Table.PostRevision)
|
||||
do! conn.customNonQuery
|
||||
@@ -94,18 +94,18 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
as_of TEXT NOT NULL,
|
||||
revision_text TEXT NOT NULL,
|
||||
PRIMARY KEY (post_id, as_of))" []
|
||||
|
||||
|
||||
if needsTable Table.PostComment then
|
||||
log.LogInformation(creatingTable, Table.PostComment)
|
||||
do! conn.ensureTable Table.PostComment
|
||||
do! conn.ensureFieldIndex Table.PostComment "post" [ nameof Comment.Empty.PostId ]
|
||||
|
||||
|
||||
// Tag map table
|
||||
if needsTable Table.TagMap then
|
||||
log.LogInformation(creatingTable, Table.TagMap)
|
||||
do! conn.ensureTable Table.TagMap
|
||||
do! conn.ensureFieldIndex Table.TagMap "url" [ nameof TagMap.Empty.WebLogId; nameof TagMap.Empty.UrlValue ]
|
||||
|
||||
|
||||
// Uploaded file table
|
||||
if needsTable Table.Upload then
|
||||
log.LogInformation(creatingTable, Table.Upload)
|
||||
@@ -117,7 +117,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
updated_on TEXT NOT NULL,
|
||||
data BLOB NOT NULL);
|
||||
CREATE INDEX idx_{Table.Upload}_path ON {Table.Upload} (web_log_id, path)" []
|
||||
|
||||
|
||||
// Database version table
|
||||
if needsTable Table.DbVersion then
|
||||
log.LogInformation(creatingTable, Table.DbVersion)
|
||||
@@ -125,11 +125,11 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
$"CREATE TABLE {Table.DbVersion} (id TEXT PRIMARY KEY);
|
||||
INSERT INTO {Table.DbVersion} VALUES ('{Utils.Migration.currentDbVersion}')" []
|
||||
}
|
||||
|
||||
|
||||
/// Set the database version to the specified version
|
||||
let setDbVersion version =
|
||||
conn.customNonQuery $"DELETE FROM {Table.DbVersion}; INSERT INTO {Table.DbVersion} VALUES ('%s{version}')" []
|
||||
|
||||
|
||||
/// Implement the changes between v2-rc1 and v2-rc2
|
||||
let migrateV2Rc1ToV2Rc2 () = backgroundTask {
|
||||
let logStep = Utils.Migration.logStep log "v2-rc1 to v2-rc2"
|
||||
@@ -223,7 +223,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
|> Option.map (Utils.deserialize<Chapter list> ser)
|
||||
ChapterFile = Map.tryString "chapter_file" epRdr
|
||||
ChapterType = Map.tryString "chapter_type" epRdr
|
||||
ChapterWaypoints = None
|
||||
ChapterWaypoints = None
|
||||
TranscriptUrl = Map.tryString "transcript_url" epRdr
|
||||
TranscriptType = Map.tryString "transcript_type" epRdr
|
||||
TranscriptLang = Map.tryString "transcript_lang" epRdr
|
||||
@@ -241,7 +241,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
cmd.Parameters.AddWithValue("@id", string postId) ] |> ignore
|
||||
let _ = cmd.ExecuteNonQuery()
|
||||
cmd.Parameters.Clear())
|
||||
|
||||
|
||||
logStep "Migrating dates/times"
|
||||
let inst (dt: DateTime) =
|
||||
DateTime(dt.Ticks, DateTimeKind.Utc)
|
||||
@@ -408,10 +408,10 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
let _ = cmd.ExecuteNonQuery()
|
||||
())
|
||||
cmd.Parameters.Clear()
|
||||
|
||||
|
||||
conn.Close()
|
||||
conn.Open()
|
||||
|
||||
|
||||
logStep "Dropping old tables and columns"
|
||||
cmd.CommandText <-
|
||||
"ALTER TABLE web_log_user DROP COLUMN salt;
|
||||
@@ -420,11 +420,11 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
DROP TABLE page_meta;
|
||||
DROP TABLE web_log_feed_podcast"
|
||||
do! write cmd
|
||||
|
||||
|
||||
logStep "Setting database version to v2-rc2"
|
||||
do! setDbVersion "v2-rc2"
|
||||
}
|
||||
|
||||
|
||||
/// Migrate from v2-rc2 to v2
|
||||
let migrateV2Rc2ToV2 () = backgroundTask {
|
||||
Utils.Migration.logStep log "v2-rc2 to v2" "Setting database version; no migration required"
|
||||
@@ -443,7 +443,7 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
Utils.Migration.logStep log "v2.1 to v2.1.1" "Setting database version; no migration required"
|
||||
do! setDbVersion "v2.1.1"
|
||||
}
|
||||
|
||||
|
||||
/// Migrate from v2.1.1 to v2.2
|
||||
let migrateV2point1point1ToV2point2 () = backgroundTask {
|
||||
Utils.Migration.logStep log "v2.1.1 to v2.2" "Setting e-mail to lowercase"
|
||||
@@ -452,6 +452,14 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
do! setDbVersion "v2.2"
|
||||
}
|
||||
|
||||
/// Migrate from v2.2 to v3
|
||||
let migrateV2point2ToV3 () = backgroundTask {
|
||||
Utils.Migration.logStep log "v2.2 to v3" "Adding auto-OpenGraph flag to all web logs"
|
||||
do! Patch.byFields Table.WebLog Any [ Field.Exists (nameof WebLog.Empty.Id) ] {| AutoOpenGraph = true |}
|
||||
Utils.Migration.logStep log "v2.2 to v3" "Setting database version to v3"
|
||||
do! setDbVersion "v3"
|
||||
}
|
||||
|
||||
/// Migrate data among versions (up only)
|
||||
let migrate version = backgroundTask {
|
||||
let mutable v = defaultArg version ""
|
||||
@@ -459,33 +467,37 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
if v = "v2-rc1" then
|
||||
do! migrateV2Rc1ToV2Rc2 ()
|
||||
v <- "v2-rc2"
|
||||
|
||||
|
||||
if v = "v2-rc2" then
|
||||
do! migrateV2Rc2ToV2 ()
|
||||
v <- "v2"
|
||||
|
||||
|
||||
if v = "v2" then
|
||||
do! migrateV2ToV2point1 ()
|
||||
v <- "v2.1"
|
||||
|
||||
|
||||
if v = "v2.1" then
|
||||
do! migrateV2point1ToV2point1point1 ()
|
||||
v <- "v2.1.1"
|
||||
|
||||
|
||||
if v = "v2.1.1" then
|
||||
do! migrateV2point1point1ToV2point2 ()
|
||||
v <- "v2.2"
|
||||
|
||||
|
||||
if v = "v2.2" then
|
||||
do! migrateV2point2ToV3 ()
|
||||
v <- "v3"
|
||||
|
||||
if v <> Utils.Migration.currentDbVersion then
|
||||
log.LogWarning $"Unknown database version; assuming {Utils.Migration.currentDbVersion}"
|
||||
do! setDbVersion Utils.Migration.currentDbVersion
|
||||
}
|
||||
|
||||
|
||||
/// The connection for this instance
|
||||
member _.Conn = conn
|
||||
|
||||
|
||||
interface IData with
|
||||
|
||||
|
||||
member _.Category = SQLiteCategoryData (conn, ser, log)
|
||||
member _.Page = SQLitePageData (conn, log)
|
||||
member _.Post = SQLitePostData (conn, log)
|
||||
@@ -495,9 +507,9 @@ type SQLiteData(conn: SqliteConnection, log: ILogger<SQLiteData>, ser: JsonSeria
|
||||
member _.Upload = SQLiteUploadData (conn, log)
|
||||
member _.WebLog = SQLiteWebLogData (conn, log)
|
||||
member _.WebLogUser = SQLiteWebLogUserData (conn, log)
|
||||
|
||||
|
||||
member _.Serializer = ser
|
||||
|
||||
|
||||
member _.StartUp () = backgroundTask {
|
||||
do! ensureTables ()
|
||||
let! version = conn.customSingle<string> $"SELECT id FROM {Table.DbVersion}" [] _.GetString(0)
|
||||
|
||||
Reference in New Issue
Block a user