Version 2.1 (#41)
- Add full chapter support (#6) - Add built-in redirect functionality (#39) - Support building Docker containers for release (#38) - Support canonical domain configuration (#37) - Add unit tests for domain/models and integration tests for all three data stores - Convert SQLite storage to use JSON documents, similar to PostgreSQL - Convert admin templates to Giraffe View Engine (from Liquid) - Add .NET 8 support
This commit was merged in pull request #41.
This commit is contained in:
+233
-188
@@ -69,20 +69,20 @@ module private RethinkHelpers =
|
||||
let r = RethinkDB.R
|
||||
|
||||
/// Verify that the web log ID matches before returning an item
|
||||
let verifyWebLog<'T> webLogId (prop : 'T -> WebLogId) (f : Net.IConnection -> Task<'T option>) =
|
||||
let verifyWebLog<'T> webLogId (prop: 'T -> WebLogId) (f: Net.IConnection -> Task<'T option>) =
|
||||
fun conn -> backgroundTask {
|
||||
match! f conn with Some it when (prop it) = webLogId -> return Some it | _ -> return None
|
||||
}
|
||||
|
||||
/// Get the first item from a list, or None if the list is empty
|
||||
let tryFirst<'T> (f : Net.IConnection -> Task<'T list>) =
|
||||
let tryFirst<'T> (f: Net.IConnection -> Task<'T list>) =
|
||||
fun conn -> backgroundTask {
|
||||
let! results = f conn
|
||||
return results |> List.tryHead
|
||||
}
|
||||
|
||||
/// Cast a strongly-typed list to an object list
|
||||
let objList<'T> (objects : 'T list) = objects |> List.map (fun it -> it :> obj)
|
||||
let objList<'T> (objects: 'T list) = objects |> List.map (fun it -> it :> obj)
|
||||
|
||||
|
||||
open System
|
||||
@@ -92,16 +92,16 @@ open RethinkDb.Driver.FSharp
|
||||
open RethinkHelpers
|
||||
|
||||
/// RethinkDB implementation of data functions for myWebLog
|
||||
type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<RethinkDbData>) =
|
||||
type RethinkDbData(conn: Net.IConnection, config: DataConfig, log: ILogger<RethinkDbData>) =
|
||||
|
||||
/// Match theme asset IDs by their prefix (the theme ID)
|
||||
let matchAssetByThemeId themeId =
|
||||
let keyPrefix = $"^{ThemeId.toString themeId}/"
|
||||
fun (row : Ast.ReqlExpr) -> row[nameof ThemeAsset.empty.Id].Match keyPrefix :> obj
|
||||
let keyPrefix = $"^{themeId}/"
|
||||
fun (row: Ast.ReqlExpr) -> row[nameof ThemeAsset.Empty.Id].Match keyPrefix :> obj
|
||||
|
||||
/// Function to exclude template text from themes
|
||||
let withoutTemplateText (row : Ast.ReqlExpr) : obj =
|
||||
{| Templates = row[nameof Theme.empty.Templates].Without [| nameof ThemeTemplate.empty.Text |] |}
|
||||
let withoutTemplateText (row: Ast.ReqlExpr) : obj =
|
||||
{| Templates = row[nameof Theme.Empty.Templates].Merge(r.HashMap(nameof ThemeTemplate.Empty.Text, "")) |}
|
||||
|
||||
/// Ensure field indexes exist, as well as special indexes for selected tables
|
||||
let ensureIndexes table fields = backgroundTask {
|
||||
@@ -112,27 +112,27 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
do! rethink { withTable table; indexCreate field; write; withRetryOnce; ignoreResult conn }
|
||||
// Post and page need index by web log ID and permalink
|
||||
if [ Table.Page; Table.Post ] |> List.contains table then
|
||||
let permalinkIdx = nameof Page.empty.Permalink
|
||||
let permalinkIdx = nameof Page.Empty.Permalink
|
||||
if not (indexes |> List.contains permalinkIdx) then
|
||||
log.LogInformation $"Creating index {table}.{permalinkIdx}..."
|
||||
do! rethink {
|
||||
withTable table
|
||||
indexCreate permalinkIdx
|
||||
(fun row -> r.Array (row[nameof Page.empty.WebLogId], row[permalinkIdx].Downcase ()) :> obj)
|
||||
(fun row -> r.Array(row[nameof Page.Empty.WebLogId], row[permalinkIdx].Downcase()) :> obj)
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
// Prior permalinks are searched when a post or page permalink do not match the current URL
|
||||
let priorIdx = nameof Post.empty.PriorPermalinks
|
||||
let priorIdx = nameof Post.Empty.PriorPermalinks
|
||||
if not (indexes |> List.contains priorIdx) then
|
||||
log.LogInformation $"Creating index {table}.{priorIdx}..."
|
||||
do! rethink {
|
||||
withTable table
|
||||
indexCreate priorIdx (fun row -> row[priorIdx].Downcase () :> obj) [ Multi ]
|
||||
indexCreate priorIdx [ Multi ]
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
// Post needs indexes by category and tag (used for counting and retrieving posts)
|
||||
if Table.Post = table then
|
||||
for idx in [ nameof Post.empty.CategoryIds; nameof Post.empty.Tags ] do
|
||||
for idx in [ nameof Post.Empty.CategoryIds; nameof Post.Empty.Tags ] do
|
||||
if not (List.contains idx indexes) then
|
||||
log.LogInformation $"Creating index {table}.{idx}..."
|
||||
do! rethink {
|
||||
@@ -147,7 +147,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
do! rethink {
|
||||
withTable table
|
||||
indexCreate Index.WebLogAndTag (fun row ->
|
||||
[| row[nameof TagMap.empty.WebLogId]; row[nameof TagMap.empty.Tag] |] :> obj)
|
||||
[| row[nameof TagMap.Empty.WebLogId]; row[nameof TagMap.Empty.Tag] |] :> obj)
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
if not (indexes |> List.contains Index.WebLogAndUrl) then
|
||||
@@ -155,7 +155,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
do! rethink {
|
||||
withTable table
|
||||
indexCreate Index.WebLogAndUrl (fun row ->
|
||||
[| row[nameof TagMap.empty.WebLogId]; row[nameof TagMap.empty.UrlValue] |] :> obj)
|
||||
[| row[nameof TagMap.Empty.WebLogId]; row[nameof TagMap.Empty.UrlValue] |] :> obj)
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
// Uploaded files need an index by web log ID and path, as that is how they are retrieved
|
||||
@@ -165,7 +165,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
do! rethink {
|
||||
withTable table
|
||||
indexCreate Index.WebLogAndPath (fun row ->
|
||||
[| row[nameof Upload.empty.WebLogId]; row[nameof Upload.empty.Path] |] :> obj)
|
||||
[| row[nameof Upload.Empty.WebLogId]; row[nameof Upload.Empty.Path] |] :> obj)
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
// Users log on with e-mail
|
||||
@@ -175,14 +175,18 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
do! rethink {
|
||||
withTable table
|
||||
indexCreate Index.LogOn (fun row ->
|
||||
[| row[nameof WebLogUser.empty.WebLogId]; row[nameof WebLogUser.empty.Email] |] :> obj)
|
||||
[| row[nameof WebLogUser.Empty.WebLogId]; row[nameof WebLogUser.Empty.Email] |] :> obj)
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
do! rethink { withTable table; indexWait; result; withRetryDefault; ignoreResult conn }
|
||||
}
|
||||
|
||||
/// The batch size for restoration methods
|
||||
let restoreBatchSize = 100
|
||||
|
||||
/// A value to use when files need to be retrieved without their data
|
||||
let emptyFile = r.Binary(Array.Empty<byte>())
|
||||
|
||||
/// Delete assets for the given theme ID
|
||||
let deleteAssetsByTheme themeId = rethink {
|
||||
withTable Table.ThemeAsset
|
||||
@@ -192,7 +196,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
}
|
||||
|
||||
/// Set a specific database version
|
||||
let setDbVersion (version : string) = backgroundTask {
|
||||
let setDbVersion (version: string) = backgroundTask {
|
||||
do! rethink {
|
||||
withTable Table.DbVersion
|
||||
delete
|
||||
@@ -207,7 +211,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
/// Migrate from v2-rc1 to v2-rc2
|
||||
let migrateV2Rc1ToV2Rc2 () = backgroundTask {
|
||||
let logStep = Utils.logMigrationStep log "v2-rc1 to v2-rc2"
|
||||
let logStep = Utils.Migration.logStep log "v2-rc1 to v2-rc2"
|
||||
logStep "**IMPORTANT**"
|
||||
logStep "See release notes about required backup/restoration for RethinkDB."
|
||||
logStep "If there is an error immediately below this message, this is why."
|
||||
@@ -217,20 +221,42 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
/// Migrate from v2-rc2 to v2
|
||||
let migrateV2Rc2ToV2 () = backgroundTask {
|
||||
Utils.logMigrationStep log "v2-rc2 to v2" "Setting database version; no migration required"
|
||||
Utils.Migration.logStep log "v2-rc2 to v2" "Setting database version; no migration required"
|
||||
do! setDbVersion "v2"
|
||||
}
|
||||
|
||||
/// Migrate from v2 to v2.1
|
||||
let migrateV2ToV2point1 () = backgroundTask {
|
||||
Utils.Migration.logStep log "v2 to v2.1" "Adding empty redirect rule set to all weblogs"
|
||||
do! rethink {
|
||||
withTable Table.WebLog
|
||||
update [ nameof WebLog.Empty.RedirectRules, [] :> obj ]
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
|
||||
Utils.Migration.logStep log "v2 to v2.1" "Setting database version to v2.1"
|
||||
do! setDbVersion "v2.1"
|
||||
}
|
||||
|
||||
/// Migrate data between versions
|
||||
let migrate version = backgroundTask {
|
||||
match version with
|
||||
| Some v when v = "v2" -> ()
|
||||
| Some v when v = "v2-rc2" -> do! migrateV2Rc2ToV2 ()
|
||||
| Some v when v = "v2-rc1" -> do! migrateV2Rc1ToV2Rc2 ()
|
||||
| Some _
|
||||
| None ->
|
||||
log.LogWarning $"Unknown database version; assuming {Utils.currentDbVersion}"
|
||||
do! setDbVersion Utils.currentDbVersion
|
||||
let mutable v = defaultArg version ""
|
||||
|
||||
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 <> Utils.Migration.currentDbVersion then
|
||||
log.LogWarning $"Unknown database version; assuming {Utils.Migration.currentDbVersion}"
|
||||
do! setDbVersion Utils.Migration.currentDbVersion
|
||||
}
|
||||
|
||||
/// The connection for this instance
|
||||
@@ -249,15 +275,15 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.CountAll webLogId = rethink<int> {
|
||||
withTable Table.Category
|
||||
getAll [ webLogId ] (nameof Category.empty.WebLogId)
|
||||
getAll [ webLogId ] (nameof Category.Empty.WebLogId)
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
member _.CountTopLevel webLogId = rethink<int> {
|
||||
withTable Table.Category
|
||||
getAll [ webLogId ] (nameof Category.empty.WebLogId)
|
||||
filter (nameof Category.empty.ParentId) None
|
||||
getAll [ webLogId ] (nameof Category.Empty.WebLogId)
|
||||
filter (nameof Category.Empty.ParentId) None (Default FilterDefaultHandling.Return)
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
@@ -265,8 +291,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
member _.FindAllForView webLogId = backgroundTask {
|
||||
let! cats = rethink<Category list> {
|
||||
withTable Table.Category
|
||||
getAll [ webLogId ] (nameof Category.empty.WebLogId)
|
||||
orderByFunc (fun it -> it[nameof Category.empty.Name].Downcase () :> obj)
|
||||
getAll [ webLogId ] (nameof Category.Empty.WebLogId)
|
||||
orderByFunc (fun it -> it[nameof Category.Empty.Name].Downcase() :> obj)
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
let ordered = Utils.orderByHierarchy cats None None []
|
||||
@@ -282,8 +308,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|> List.ofSeq
|
||||
let! count = rethink<int> {
|
||||
withTable Table.Post
|
||||
getAll catIds (nameof Post.empty.CategoryIds)
|
||||
filter (nameof Post.empty.Status) Published
|
||||
getAll catIds (nameof Post.Empty.CategoryIds)
|
||||
filter (nameof Post.Empty.Status) Published
|
||||
distinct
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
@@ -298,8 +324,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
PostCount = counts
|
||||
|> Array.tryFind (fun c -> fst c = cat.Id)
|
||||
|> Option.map snd
|
||||
|> Option.defaultValue 0
|
||||
})
|
||||
|> Option.defaultValue 0 })
|
||||
|> Array.ofSeq
|
||||
}
|
||||
|
||||
@@ -309,11 +334,11 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
get catId
|
||||
resultOption; withRetryOptionDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun c -> c.WebLogId) <| conn
|
||||
|> verifyWebLog webLogId _.WebLogId <| conn
|
||||
|
||||
member _.FindByWebLog webLogId = rethink<Category list> {
|
||||
withTable Table.Category
|
||||
getAll [ webLogId ] (nameof Category.empty.WebLogId)
|
||||
getAll [ webLogId ] (nameof Category.Empty.WebLogId)
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
@@ -323,24 +348,26 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
// Reassign any children to the category's parent category
|
||||
let! children = rethink<int> {
|
||||
withTable Table.Category
|
||||
filter (nameof Category.empty.ParentId) catId
|
||||
filter (nameof Category.Empty.ParentId) catId
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
if children > 0 then
|
||||
do! rethink {
|
||||
withTable Table.Category
|
||||
filter (nameof Category.empty.ParentId) catId
|
||||
update [ nameof Category.empty.ParentId, cat.ParentId :> obj ]
|
||||
filter (nameof Category.Empty.ParentId) catId
|
||||
update [ nameof Category.Empty.ParentId, cat.ParentId :> obj ]
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
// Delete the category off all posts where it is assigned
|
||||
do! rethink {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
filter (fun row -> row[nameof Post.empty.CategoryIds].Contains catId :> obj)
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
filter (fun row -> row[nameof Post.Empty.CategoryIds].Contains catId :> obj)
|
||||
update (fun row ->
|
||||
{| CategoryIds = r.Array(row[nameof Post.empty.CategoryIds]).Remove catId |} :> obj)
|
||||
{| CategoryIds =
|
||||
row[nameof Post.Empty.CategoryIds].CoerceTo("array")
|
||||
.SetDifference(r.Array(catId)) |} :> obj)
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
// Delete the category itself
|
||||
@@ -386,26 +413,26 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.All webLogId = rethink<Page list> {
|
||||
withTable Table.Page
|
||||
getAll [ webLogId ] (nameof Page.empty.WebLogId)
|
||||
without [ nameof Page.empty.Text
|
||||
nameof Page.empty.Metadata
|
||||
nameof Page.empty.Revisions
|
||||
nameof Page.empty.PriorPermalinks ]
|
||||
orderByFunc (fun row -> row[nameof Page.empty.Title].Downcase () :> obj)
|
||||
getAll [ webLogId ] (nameof Page.Empty.WebLogId)
|
||||
merge (r.HashMap(nameof Page.Empty.Text, "")
|
||||
.With(nameof Page.Empty.Metadata, [||])
|
||||
.With(nameof Page.Empty.Revisions, [||])
|
||||
.With(nameof Page.Empty.PriorPermalinks, [||]))
|
||||
orderByFunc (fun row -> row[nameof Page.Empty.Title].Downcase() :> obj)
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
member _.CountAll webLogId = rethink<int> {
|
||||
withTable Table.Page
|
||||
getAll [ webLogId ] (nameof Page.empty.WebLogId)
|
||||
getAll [ webLogId ] (nameof Page.Empty.WebLogId)
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
member _.CountListed webLogId = rethink<int> {
|
||||
withTable Table.Page
|
||||
getAll [ webLogId ] (nameof Page.empty.WebLogId)
|
||||
filter (nameof Page.empty.IsInPageList) true
|
||||
getAll [ webLogId ] (nameof Page.Empty.WebLogId)
|
||||
filter (nameof Page.Empty.IsInPageList) true
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
@@ -414,7 +441,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
let! result = rethink<Model.Result> {
|
||||
withTable Table.Page
|
||||
getAll [ pageId ]
|
||||
filter (fun row -> row[nameof Page.empty.WebLogId].Eq webLogId :> obj)
|
||||
filter (fun row -> row[nameof Page.Empty.WebLogId].Eq webLogId :> obj)
|
||||
delete
|
||||
write; withRetryDefault conn
|
||||
}
|
||||
@@ -422,19 +449,22 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
}
|
||||
|
||||
member _.FindById pageId webLogId =
|
||||
rethink<Page> {
|
||||
rethink<Page list> {
|
||||
withTable Table.Page
|
||||
get pageId
|
||||
without [ nameof Page.empty.PriorPermalinks; nameof Page.empty.Revisions ]
|
||||
resultOption; withRetryOptionDefault
|
||||
getAll [ pageId ]
|
||||
filter (nameof Page.Empty.WebLogId) webLogId
|
||||
merge (r.HashMap(nameof Page.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Page.Empty.Revisions, [||]))
|
||||
result; withRetryDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun it -> it.WebLogId) <| conn
|
||||
|> tryFirst <| conn
|
||||
|
||||
member _.FindByPermalink permalink webLogId =
|
||||
rethink<Page list> {
|
||||
withTable Table.Page
|
||||
getAll [ [| webLogId :> obj; permalink |] ] (nameof Page.empty.Permalink)
|
||||
without [ nameof Page.empty.PriorPermalinks; nameof Page.empty.Revisions ]
|
||||
getAll [ [| webLogId :> obj; permalink |] ] (nameof Page.Empty.Permalink)
|
||||
merge (r.HashMap(nameof Page.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Page.Empty.Revisions, [||]))
|
||||
limit 1
|
||||
result; withRetryDefault
|
||||
}
|
||||
@@ -444,14 +474,14 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
let! result =
|
||||
(rethink<Page list> {
|
||||
withTable Table.Page
|
||||
getAll (objList permalinks) (nameof Page.empty.PriorPermalinks)
|
||||
filter (nameof Page.empty.WebLogId) webLogId
|
||||
without [ nameof Page.empty.Revisions; nameof Page.empty.Text ]
|
||||
getAll (objList permalinks) (nameof Page.Empty.PriorPermalinks)
|
||||
filter (nameof Page.Empty.WebLogId) webLogId
|
||||
without [ nameof Page.Empty.Revisions; nameof Page.Empty.Text ]
|
||||
limit 1
|
||||
result; withRetryDefault
|
||||
}
|
||||
|> tryFirst) conn
|
||||
return result |> Option.map (fun pg -> pg.Permalink)
|
||||
return result |> Option.map _.Permalink
|
||||
}
|
||||
|
||||
member _.FindFullById pageId webLogId =
|
||||
@@ -460,30 +490,32 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
get pageId
|
||||
resultOption; withRetryOptionDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun it -> it.WebLogId) <| conn
|
||||
|> verifyWebLog webLogId _.WebLogId <| conn
|
||||
|
||||
member _.FindFullByWebLog webLogId = rethink<Page> {
|
||||
withTable Table.Page
|
||||
getAll [ webLogId ] (nameof Page.empty.WebLogId)
|
||||
getAll [ webLogId ] (nameof Page.Empty.WebLogId)
|
||||
resultCursor; withRetryCursorDefault; toList conn
|
||||
}
|
||||
|
||||
member _.FindListed webLogId = rethink<Page list> {
|
||||
withTable Table.Page
|
||||
getAll [ webLogId ] (nameof Page.empty.WebLogId)
|
||||
filter [ nameof Page.empty.IsInPageList, true :> obj ]
|
||||
without [ nameof Page.empty.Text; nameof Page.empty.PriorPermalinks; nameof Page.empty.Revisions ]
|
||||
orderBy (nameof Page.empty.Title)
|
||||
getAll [ webLogId ] (nameof Page.Empty.WebLogId)
|
||||
filter [ nameof Page.Empty.IsInPageList, true :> obj ]
|
||||
merge (r.HashMap(nameof Page.Empty.Text, "")
|
||||
.With(nameof Page.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Page.Empty.Revisions, [||]))
|
||||
orderBy (nameof Page.Empty.Title)
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
member _.FindPageOfPages webLogId pageNbr = rethink<Page list> {
|
||||
withTable Table.Page
|
||||
getAll [ webLogId ] (nameof Page.empty.WebLogId)
|
||||
without [ nameof Page.empty.Metadata
|
||||
nameof Page.empty.PriorPermalinks
|
||||
nameof Page.empty.Revisions ]
|
||||
orderByFunc (fun row -> row[nameof Page.empty.Title].Downcase ())
|
||||
getAll [ webLogId ] (nameof Page.Empty.WebLogId)
|
||||
merge (r.HashMap(nameof Page.Empty.Metadata, [||])
|
||||
.With(nameof Page.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Page.Empty.Revisions, [||]))
|
||||
orderByFunc (fun row -> row[nameof Page.Empty.Title].Downcase())
|
||||
skip ((pageNbr - 1) * 25)
|
||||
limit 25
|
||||
result; withRetryDefault conn
|
||||
@@ -511,7 +543,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
nameof page.PriorPermalinks, page.PriorPermalinks
|
||||
nameof page.Metadata, page.Metadata
|
||||
nameof page.Revisions, page.Revisions
|
||||
]
|
||||
]
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
|
||||
@@ -521,7 +553,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
do! rethink {
|
||||
withTable Table.Page
|
||||
get pageId
|
||||
update [ nameof Page.empty.PriorPermalinks, permalinks :> obj ]
|
||||
update [ nameof Page.Empty.PriorPermalinks, permalinks :> obj ]
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
return true
|
||||
@@ -540,8 +572,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.CountByStatus status webLogId = rethink<int> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
filter (nameof Post.empty.Status) status
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
filter (nameof Post.Empty.Status) status
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
@@ -550,7 +582,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
let! result = rethink<Model.Result> {
|
||||
withTable Table.Post
|
||||
getAll [ postId ]
|
||||
filter (fun row -> row[nameof Post.empty.WebLogId].Eq webLogId :> obj)
|
||||
filter (fun row -> row[nameof Post.Empty.WebLogId].Eq webLogId :> obj)
|
||||
delete
|
||||
write; withRetryDefault conn
|
||||
}
|
||||
@@ -558,19 +590,22 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
}
|
||||
|
||||
member _.FindById postId webLogId =
|
||||
rethink<Post> {
|
||||
rethink<Post list> {
|
||||
withTable Table.Post
|
||||
get postId
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
resultOption; withRetryOptionDefault
|
||||
getAll [ postId ]
|
||||
filter (nameof Post.Empty.WebLogId) webLogId
|
||||
merge (r.HashMap(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
result; withRetryDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun p -> p.WebLogId) <| conn
|
||||
|> tryFirst <| conn
|
||||
|
||||
member _.FindByPermalink permalink webLogId =
|
||||
rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll [ [| webLogId :> obj; permalink |] ] (nameof Post.empty.Permalink)
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
getAll [ [| webLogId :> obj; permalink |] ] (nameof Post.Empty.Permalink)
|
||||
merge (r.HashMap(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
limit 1
|
||||
result; withRetryDefault
|
||||
}
|
||||
@@ -582,36 +617,37 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
get postId
|
||||
resultOption; withRetryOptionDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun p -> p.WebLogId) <| conn
|
||||
|> verifyWebLog webLogId _.WebLogId <| conn
|
||||
|
||||
member _.FindCurrentPermalink permalinks webLogId = backgroundTask {
|
||||
let! result =
|
||||
(rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll (objList permalinks) (nameof Post.empty.PriorPermalinks)
|
||||
filter (nameof Post.empty.WebLogId) webLogId
|
||||
without [ nameof Post.empty.Revisions; nameof Post.empty.Text ]
|
||||
getAll (objList permalinks) (nameof Post.Empty.PriorPermalinks)
|
||||
filter (nameof Post.Empty.WebLogId) webLogId
|
||||
without [ nameof Post.Empty.Revisions; nameof Post.Empty.Text ]
|
||||
limit 1
|
||||
result; withRetryDefault
|
||||
}
|
||||
|> tryFirst) conn
|
||||
return result |> Option.map (fun post -> post.Permalink)
|
||||
return result |> Option.map _.Permalink
|
||||
}
|
||||
|
||||
member _.FindFullByWebLog webLogId = rethink<Post> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
resultCursor; withRetryCursorDefault; toList conn
|
||||
}
|
||||
|
||||
member _.FindPageOfCategorizedPosts webLogId categoryIds pageNbr postsPerPage = rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll (objList categoryIds) (nameof Post.empty.CategoryIds)
|
||||
filter [ nameof Post.empty.WebLogId, webLogId :> obj
|
||||
nameof Post.empty.Status, Published ]
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
getAll (objList categoryIds) (nameof Post.Empty.CategoryIds)
|
||||
filter [ nameof Post.Empty.WebLogId, webLogId :> obj
|
||||
nameof Post.Empty.Status, Published ]
|
||||
merge (r.HashMap(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
distinct
|
||||
orderByDescending (nameof Post.empty.PublishedOn)
|
||||
orderByDescending (nameof Post.Empty.PublishedOn)
|
||||
skip ((pageNbr - 1) * postsPerPage)
|
||||
limit (postsPerPage + 1)
|
||||
result; withRetryDefault conn
|
||||
@@ -619,10 +655,12 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.FindPageOfPosts webLogId pageNbr postsPerPage = rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
merge (r.HashMap(nameof Post.Empty.Text, "")
|
||||
.With(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
orderByFuncDescending (fun row ->
|
||||
row[nameof Post.empty.PublishedOn].Default_ (nameof Post.empty.UpdatedOn) :> obj)
|
||||
row[nameof Post.Empty.PublishedOn].Default_(nameof Post.Empty.UpdatedOn) :> obj)
|
||||
skip ((pageNbr - 1) * postsPerPage)
|
||||
limit (postsPerPage + 1)
|
||||
result; withRetryDefault conn
|
||||
@@ -630,10 +668,11 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.FindPageOfPublishedPosts webLogId pageNbr postsPerPage = rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
filter (nameof Post.empty.Status) Published
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
orderByDescending (nameof Post.empty.PublishedOn)
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
filter (nameof Post.Empty.Status) Published
|
||||
merge (r.HashMap(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
orderByDescending (nameof Post.Empty.PublishedOn)
|
||||
skip ((pageNbr - 1) * postsPerPage)
|
||||
limit (postsPerPage + 1)
|
||||
result; withRetryDefault conn
|
||||
@@ -641,11 +680,12 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.FindPageOfTaggedPosts webLogId tag pageNbr postsPerPage = rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll [ tag ] (nameof Post.empty.Tags)
|
||||
filter [ nameof Post.empty.WebLogId, webLogId :> obj
|
||||
nameof Post.empty.Status, Published ]
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
orderByDescending (nameof Post.empty.PublishedOn)
|
||||
getAll [ tag ] (nameof Post.Empty.Tags)
|
||||
filter [ nameof Post.Empty.WebLogId, webLogId :> obj
|
||||
nameof Post.Empty.Status, Published ]
|
||||
merge (r.HashMap(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
orderByDescending (nameof Post.Empty.PublishedOn)
|
||||
skip ((pageNbr - 1) * postsPerPage)
|
||||
limit (postsPerPage + 1)
|
||||
result; withRetryDefault conn
|
||||
@@ -655,10 +695,11 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
let! older =
|
||||
rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
filter (fun row -> row[nameof Post.empty.PublishedOn].Lt publishedOn :> obj)
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
orderByDescending (nameof Post.empty.PublishedOn)
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
filter (fun row -> row[nameof Post.Empty.PublishedOn].Lt publishedOn :> obj)
|
||||
merge (r.HashMap(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
orderByDescending (nameof Post.Empty.PublishedOn)
|
||||
limit 1
|
||||
result; withRetryDefault
|
||||
}
|
||||
@@ -666,10 +707,11 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
let! newer =
|
||||
rethink<Post list> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
filter (fun row -> row[nameof Post.empty.PublishedOn].Gt publishedOn :> obj)
|
||||
without [ nameof Post.empty.PriorPermalinks; nameof Post.empty.Revisions ]
|
||||
orderBy (nameof Post.empty.PublishedOn)
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
filter (fun row -> row[nameof Post.Empty.PublishedOn].Gt publishedOn :> obj)
|
||||
merge (r.HashMap(nameof Post.Empty.PriorPermalinks, [||])
|
||||
.With(nameof Post.Empty.Revisions, [||]))
|
||||
orderBy (nameof Post.Empty.PublishedOn)
|
||||
limit 1
|
||||
result; withRetryDefault
|
||||
}
|
||||
@@ -686,27 +728,25 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
}
|
||||
}
|
||||
|
||||
member _.Update post = rethink {
|
||||
withTable Table.Post
|
||||
get post.Id
|
||||
replace post
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
member this.Update post = backgroundTask {
|
||||
match! this.FindById post.Id post.WebLogId with
|
||||
| Some _ ->
|
||||
do! rethink {
|
||||
withTable Table.Post
|
||||
get post.Id
|
||||
replace post
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
| None -> ()
|
||||
}
|
||||
|
||||
member _.UpdatePriorPermalinks postId webLogId permalinks = backgroundTask {
|
||||
match! (
|
||||
rethink<Post> {
|
||||
withTable Table.Post
|
||||
get postId
|
||||
without [ nameof Post.empty.Revisions; nameof Post.empty.PriorPermalinks ]
|
||||
resultOption; withRetryOptionDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun p -> p.WebLogId)) conn with
|
||||
member this.UpdatePriorPermalinks postId webLogId permalinks = backgroundTask {
|
||||
match! this.FindById postId webLogId with
|
||||
| Some _ ->
|
||||
do! rethink {
|
||||
withTable Table.Post
|
||||
get postId
|
||||
update [ nameof Post.empty.PriorPermalinks, permalinks :> obj ]
|
||||
update [ nameof Post.Empty.PriorPermalinks, permalinks :> obj ]
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
return true
|
||||
@@ -721,7 +761,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
let! result = rethink<Model.Result> {
|
||||
withTable Table.TagMap
|
||||
getAll [ tagMapId ]
|
||||
filter (fun row -> row[nameof TagMap.empty.WebLogId].Eq webLogId :> obj)
|
||||
filter (fun row -> row[nameof TagMap.Empty.WebLogId].Eq webLogId :> obj)
|
||||
delete
|
||||
write; withRetryDefault conn
|
||||
}
|
||||
@@ -734,7 +774,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
get tagMapId
|
||||
resultOption; withRetryOptionDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun tm -> tm.WebLogId) <| conn
|
||||
|> verifyWebLog webLogId _.WebLogId <| conn
|
||||
|
||||
member _.FindByUrlValue urlValue webLogId =
|
||||
rethink<TagMap list> {
|
||||
@@ -747,9 +787,9 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.FindByWebLog webLogId = rethink<TagMap list> {
|
||||
withTable Table.TagMap
|
||||
between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |]
|
||||
between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |]
|
||||
[ Index Index.WebLogAndTag ]
|
||||
orderBy (nameof TagMap.empty.Tag)
|
||||
orderBy (nameof TagMap.Empty.Tag)
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
@@ -781,16 +821,16 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.All () = rethink<Theme list> {
|
||||
withTable Table.Theme
|
||||
filter (fun row -> row[nameof Theme.empty.Id].Ne "admin" :> obj)
|
||||
filter (fun row -> row[nameof Theme.Empty.Id].Ne "admin" :> obj)
|
||||
merge withoutTemplateText
|
||||
orderBy (nameof Theme.empty.Id)
|
||||
orderBy (nameof Theme.Empty.Id)
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
member _.Exists themeId = backgroundTask {
|
||||
let! count = rethink<int> {
|
||||
withTable Table.Theme
|
||||
filter (nameof Theme.empty.Id) themeId
|
||||
filter (nameof Theme.Empty.Id) themeId
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
@@ -803,12 +843,14 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
resultOption; withRetryOptionDefault conn
|
||||
}
|
||||
|
||||
member _.FindByIdWithoutText themeId = rethink<Theme> {
|
||||
withTable Table.Theme
|
||||
get themeId
|
||||
merge withoutTemplateText
|
||||
resultOption; withRetryOptionDefault conn
|
||||
}
|
||||
member _.FindByIdWithoutText themeId =
|
||||
rethink<Theme list> {
|
||||
withTable Table.Theme
|
||||
getAll [ themeId ]
|
||||
merge withoutTemplateText
|
||||
result; withRetryDefault
|
||||
}
|
||||
|> tryFirst <| conn
|
||||
|
||||
member this.Delete themeId = backgroundTask {
|
||||
match! this.FindByIdWithoutText themeId with
|
||||
@@ -837,7 +879,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.All () = rethink<ThemeAsset list> {
|
||||
withTable Table.ThemeAsset
|
||||
without [ nameof ThemeAsset.empty.Data ]
|
||||
merge (r.HashMap(nameof ThemeAsset.Empty.Data, emptyFile))
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
@@ -852,7 +894,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
member _.FindByTheme themeId = rethink<ThemeAsset list> {
|
||||
withTable Table.ThemeAsset
|
||||
filter (matchAssetByThemeId themeId)
|
||||
without [ nameof ThemeAsset.empty.Data ]
|
||||
merge (r.HashMap(nameof ThemeAsset.Empty.Data, emptyFile))
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
@@ -886,7 +928,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
get uploadId
|
||||
resultOption; withRetryOptionDefault
|
||||
}
|
||||
|> verifyWebLog<Upload> webLogId (fun u -> u.WebLogId) <| conn
|
||||
|> verifyWebLog<Upload> webLogId _.WebLogId <| conn
|
||||
match upload with
|
||||
| Some up ->
|
||||
do! rethink {
|
||||
@@ -895,8 +937,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
delete
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
return Ok (Permalink.toString up.Path)
|
||||
| None -> return Result.Error $"Upload ID {UploadId.toString uploadId} not found"
|
||||
return Ok (string up.Path)
|
||||
| None -> return Result.Error $"Upload ID {uploadId} not found"
|
||||
}
|
||||
|
||||
member _.FindByPath path webLogId =
|
||||
@@ -909,15 +951,15 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.FindByWebLog webLogId = rethink<Upload> {
|
||||
withTable Table.Upload
|
||||
between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |]
|
||||
between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |]
|
||||
[ Index Index.WebLogAndPath ]
|
||||
without [ nameof Upload.empty.Data ]
|
||||
merge (r.HashMap(nameof Upload.Empty.Data, emptyFile))
|
||||
resultCursor; withRetryCursorDefault; toList conn
|
||||
}
|
||||
|
||||
member _.FindByWebLogWithData webLogId = rethink<Upload> {
|
||||
withTable Table.Upload
|
||||
between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |]
|
||||
between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |]
|
||||
[ Index Index.WebLogAndPath ]
|
||||
resultCursor; withRetryCursorDefault; toList conn
|
||||
}
|
||||
@@ -926,7 +968,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
// Files can be large; we'll do 5 at a time
|
||||
for batch in uploads |> List.chunkBySize 5 do
|
||||
do! rethink {
|
||||
withTable Table.TagMap
|
||||
withTable Table.Upload
|
||||
insert batch
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
@@ -949,24 +991,24 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.Delete webLogId = backgroundTask {
|
||||
// Comments should be deleted by post IDs
|
||||
let! thePostIds = rethink<{| Id : string |} list> {
|
||||
let! thePostIds = rethink<{| Id: string |} list> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
pluck [ nameof Post.empty.Id ]
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
pluck [ nameof Post.Empty.Id ]
|
||||
result; withRetryOnce conn
|
||||
}
|
||||
if not (List.isEmpty thePostIds) then
|
||||
let postIds = thePostIds |> List.map (fun it -> it.Id :> obj)
|
||||
do! rethink {
|
||||
withTable Table.Comment
|
||||
getAll postIds (nameof Comment.empty.PostId)
|
||||
getAll postIds (nameof Comment.Empty.PostId)
|
||||
delete
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
// Tag mappings do not have a straightforward webLogId index
|
||||
do! rethink {
|
||||
withTable Table.TagMap
|
||||
between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |]
|
||||
between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |]
|
||||
[ Index Index.WebLogAndTag ]
|
||||
delete
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
@@ -974,7 +1016,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
// Uploaded files do not have a straightforward webLogId index
|
||||
do! rethink {
|
||||
withTable Table.Upload
|
||||
between [| webLogId :> obj; r.Minval () |] [| webLogId :> obj; r.Maxval () |]
|
||||
between [| webLogId :> obj; r.Minval() |] [| webLogId :> obj; r.Maxval() |]
|
||||
[ Index Index.WebLogAndPath ]
|
||||
delete
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
@@ -982,7 +1024,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
for table in [ Table.Post; Table.Category; Table.Page; Table.WebLogUser ] do
|
||||
do! rethink {
|
||||
withTable table
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
delete
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
@@ -997,7 +1039,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
member _.FindByHost url =
|
||||
rethink<WebLog list> {
|
||||
withTable Table.WebLog
|
||||
getAll [ url ] (nameof WebLog.empty.UrlBase)
|
||||
getAll [ url ] (nameof WebLog.Empty.UrlBase)
|
||||
limit 1
|
||||
result; withRetryDefault
|
||||
}
|
||||
@@ -1009,10 +1051,17 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
resultOption; withRetryOptionDefault conn
|
||||
}
|
||||
|
||||
member _.UpdateRedirectRules webLog = rethink {
|
||||
withTable Table.WebLog
|
||||
get webLog.Id
|
||||
update [ nameof WebLog.Empty.RedirectRules, webLog.RedirectRules :> obj ]
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
|
||||
member _.UpdateRssOptions webLog = rethink {
|
||||
withTable Table.WebLog
|
||||
get webLog.Id
|
||||
update [ nameof WebLog.empty.Rss, webLog.Rss :> obj ]
|
||||
update [ nameof WebLog.Empty.Rss, webLog.Rss :> obj ]
|
||||
write; withRetryDefault; ignoreResult conn
|
||||
}
|
||||
|
||||
@@ -1049,22 +1098,22 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
get userId
|
||||
resultOption; withRetryOptionDefault
|
||||
}
|
||||
|> verifyWebLog webLogId (fun u -> u.WebLogId) <| conn
|
||||
|> verifyWebLog webLogId _.WebLogId <| conn
|
||||
|
||||
member this.Delete userId webLogId = backgroundTask {
|
||||
match! this.FindById userId webLogId with
|
||||
| Some _ ->
|
||||
let! pageCount = rethink<int> {
|
||||
withTable Table.Page
|
||||
getAll [ webLogId ] (nameof Page.empty.WebLogId)
|
||||
filter (nameof Page.empty.AuthorId) userId
|
||||
getAll [ webLogId ] (nameof Page.Empty.WebLogId)
|
||||
filter (nameof Page.Empty.AuthorId) userId
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
let! postCount = rethink<int> {
|
||||
withTable Table.Post
|
||||
getAll [ webLogId ] (nameof Post.empty.WebLogId)
|
||||
filter (nameof Post.empty.AuthorId) userId
|
||||
getAll [ webLogId ] (nameof Post.Empty.WebLogId)
|
||||
filter (nameof Post.Empty.AuthorId) userId
|
||||
count
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
@@ -1092,8 +1141,8 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
|
||||
member _.FindByWebLog webLogId = rethink<WebLogUser list> {
|
||||
withTable Table.WebLogUser
|
||||
getAll [ webLogId ] (nameof WebLogUser.empty.WebLogId)
|
||||
orderByFunc (fun row -> row[nameof WebLogUser.empty.PreferredName].Downcase ())
|
||||
getAll [ webLogId ] (nameof WebLogUser.Empty.WebLogId)
|
||||
orderByFunc (fun row -> row[nameof WebLogUser.Empty.PreferredName].Downcase())
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
|
||||
@@ -1101,12 +1150,10 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
let! users = rethink<WebLogUser list> {
|
||||
withTable Table.WebLogUser
|
||||
getAll (objList userIds)
|
||||
filter (nameof WebLogUser.empty.WebLogId) webLogId
|
||||
filter (nameof WebLogUser.Empty.WebLogId) webLogId
|
||||
result; withRetryDefault conn
|
||||
}
|
||||
return
|
||||
users
|
||||
|> List.map (fun u -> { Name = WebLogUserId.toString u.Id; Value = WebLogUser.displayName u })
|
||||
return users |> List.map (fun u -> { Name = string u.Id; Value = u.DisplayName })
|
||||
}
|
||||
|
||||
member _.Restore users = backgroundTask {
|
||||
@@ -1124,7 +1171,7 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
do! rethink {
|
||||
withTable Table.WebLogUser
|
||||
get userId
|
||||
update [ nameof WebLogUser.empty.LastSeenOn, Noda.now () :> obj ]
|
||||
update [ nameof WebLogUser.Empty.LastSeenOn, Noda.now () :> obj ]
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
| None -> ()
|
||||
@@ -1169,21 +1216,19 @@ type RethinkDbData (conn : Net.IConnection, config : DataConfig, log : ILogger<R
|
||||
write; withRetryOnce; ignoreResult conn
|
||||
}
|
||||
|
||||
do! ensureIndexes Table.Category [ nameof Category.empty.WebLogId ]
|
||||
do! ensureIndexes Table.Comment [ nameof Comment.empty.PostId ]
|
||||
do! ensureIndexes Table.Page [ nameof Page.empty.WebLogId; nameof Page.empty.AuthorId ]
|
||||
do! ensureIndexes Table.Post [ nameof Post.empty.WebLogId; nameof Post.empty.AuthorId ]
|
||||
do! ensureIndexes Table.Category [ nameof Category.Empty.WebLogId ]
|
||||
do! ensureIndexes Table.Comment [ nameof Comment.Empty.PostId ]
|
||||
do! ensureIndexes Table.Page [ nameof Page.Empty.WebLogId; nameof Page.Empty.AuthorId ]
|
||||
do! ensureIndexes Table.Post [ nameof Post.Empty.WebLogId; nameof Post.Empty.AuthorId ]
|
||||
do! ensureIndexes Table.TagMap []
|
||||
do! ensureIndexes Table.Upload []
|
||||
do! ensureIndexes Table.WebLog [ nameof WebLog.empty.UrlBase ]
|
||||
do! ensureIndexes Table.WebLogUser [ nameof WebLogUser.empty.WebLogId ]
|
||||
do! ensureIndexes Table.WebLog [ nameof WebLog.Empty.UrlBase ]
|
||||
do! ensureIndexes Table.WebLogUser [ nameof WebLogUser.Empty.WebLogId ]
|
||||
|
||||
let! version = rethink<{| Id : string |} list> {
|
||||
let! version = rethink<{| Id: string |} list> {
|
||||
withTable Table.DbVersion
|
||||
limit 1
|
||||
result; withRetryOnce conn
|
||||
}
|
||||
match List.tryHead version with
|
||||
| Some v when v.Id = "v2-rc2" -> ()
|
||||
| it -> do! migrate (it |> Option.map (fun x -> x.Id))
|
||||
do! migrate (List.tryHead version |> Option.map _.Id)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user