Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Raven cache is functional, but the recent-kills list crashes RavenDB …
…with a StackOverFlowException.
- Loading branch information
Showing
18 changed files
with
539 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
namespace EveLib.RavenCache | ||
|
||
open System | ||
open Raven.Client | ||
open Raven.Client.Linq | ||
open EveLib | ||
|
||
type internal CharacterQueries(baseClient: FSharp.ICharQueries, store: IDocumentStore) = | ||
|
||
let getAccountBalance charId = async { | ||
use session = store.OpenAsyncSession() | ||
|
||
let! wallets = | ||
query { | ||
for set in session.Query<WalletSet>() do | ||
where (set.Type = WalletType.Personal && set.CharacterId = charId) | ||
select set | ||
} |> AsyncQuery.head | ||
|
||
match wallets with | ||
| None -> | ||
let! updated = baseClient.GetAccountBalance(charId) | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
| Some set when set.CachedUntil < DateTimeOffset.UtcNow -> | ||
try | ||
let! updated = baseClient.GetAccountBalance(charId) | ||
session.Delete(set) | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
with _ -> | ||
return set | ||
| Some set -> | ||
return set | ||
} | ||
|
||
interface EveLib.FSharp.ICharQueries with | ||
member x.GetAccountBalance(charId) = getAccountBalance charId | ||
interface EveLib.Async.ICharQueries with | ||
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.StartAsTask | ||
interface EveLib.Sync.ICharQueries with | ||
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.RunSynchronously |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
namespace EveLib.RavenCache | ||
|
||
open System | ||
open Raven.Client | ||
open Raven.Client.Linq | ||
open EveLib | ||
|
||
type internal CorporationQueries(baseClient: FSharp.ICorpQueries, store: IDocumentStore) = | ||
|
||
let getAccountBalance charId = async { | ||
use session = store.OpenAsyncSession() | ||
|
||
let! wallets = | ||
query { | ||
for set in session.Query<WalletSet>() do | ||
where (set.Type = WalletType.Corporate && set.CharacterId = charId) | ||
select set | ||
} |> AsyncQuery.head | ||
|
||
match wallets with | ||
| None -> | ||
let! updated = baseClient.GetAccountBalance(charId) | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
| Some set when set.CachedUntil < DateTimeOffset.UtcNow -> | ||
try | ||
let! updated = baseClient.GetAccountBalance(charId) | ||
session.Delete(set) | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
with _ -> | ||
return set | ||
| Some set -> | ||
return set | ||
} | ||
|
||
interface EveLib.FSharp.ICorpQueries with | ||
member x.GetAccountBalance(charId) = getAccountBalance charId | ||
interface EveLib.Async.ICorpQueries with | ||
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.StartAsTask | ||
interface EveLib.Sync.ICorpQueries with | ||
member x.GetAccountBalance(charId) = getAccountBalance charId |> Async.RunSynchronously |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
namespace EveLib.RavenCache | ||
|
||
open System | ||
open System.Linq | ||
open Raven.Client | ||
open Raven.Client.Linq | ||
open EveLib | ||
|
||
// this breaks because "contains" is not supported by RavenDB | ||
|
||
type internal EveQueries(baseClient: FSharp.IEveQueries, store: IDocumentStore) = | ||
|
||
let getItemNames (ids:int[]) = async { | ||
use session = store.OpenAsyncSession() | ||
|
||
// TODO: raven returns batches of 128 only. | ||
// need to detect if more id's requested, use paging. | ||
let! matches = | ||
query { | ||
for ni in session.Query<NamedItem>() do | ||
where (LinqExtensions.In(ni.ItemId, ids)) | ||
select ni | ||
} |> AsyncQuery.asIList | ||
|
||
if matches.Count = 0 then | ||
let! updated = baseClient.GetItemNames(ids) | ||
updated |> Seq.iter session.Store | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
else | ||
let outdated, stillGood = | ||
let now = DateTimeOffset.UtcNow | ||
matches | ||
|> List.ofSeq | ||
|> List.partition (fun m -> m.CachedUntil < now) | ||
|
||
let missing = | ||
stillGood | ||
|> Seq.map (fun m -> m.ItemId) | ||
|> Set.ofSeq | ||
|> Set.difference (ids |> Set.ofArray) | ||
|
||
let toLoad = | ||
outdated | ||
|> Seq.map (fun m -> m.ItemId) | ||
|> Seq.append missing | ||
|
||
if toLoad |> Seq.exists (fun _ -> true) then | ||
let! updated = baseClient.GetItemNames(toLoad |> Array.ofSeq) | ||
let merged = stillGood |> Seq.append updated |> Seq.cache | ||
outdated |> List.iter session.Delete | ||
merged |> Seq.iter session.Store | ||
do! session.AsyncSaveChanges() | ||
return merged | ||
else | ||
return upcast stillGood | ||
} | ||
|
||
let getItemIds (names:string[]) = async { | ||
use session = store.OpenAsyncSession() | ||
|
||
// TODO: raven returns batches of 128 only. | ||
// need to detect if more id's requested, use paging. | ||
let! matches = | ||
query { | ||
for ni in session.Query<NamedItem>() do | ||
where (LinqExtensions.In(ni.Name, names)) | ||
select ni | ||
} |> AsyncQuery.asIList | ||
|
||
if matches.Count = 0 then | ||
let! updated = baseClient.GetItemIds(names) | ||
updated |> Seq.iter session.Store | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
else | ||
let outdated, stillGood = | ||
let now = DateTimeOffset.UtcNow | ||
matches | ||
|> List.ofSeq | ||
|> List.partition (fun m -> m.CachedUntil < now) | ||
|
||
let missing = | ||
stillGood | ||
|> Seq.map (fun m -> m.Name) | ||
|> Set.ofSeq | ||
|> Set.difference (names |> Set.ofArray) | ||
|
||
let toLoad = | ||
outdated | ||
|> Seq.map (fun m -> m.Name) | ||
|> Seq.append missing | ||
|
||
if toLoad |> Seq.exists (fun _ -> true) then | ||
let! updated = baseClient.GetItemIds(toLoad |> Array.ofSeq) | ||
let merged = stillGood |> Seq.append updated |> Seq.cache | ||
outdated |> List.iter session.Delete | ||
merged |> Seq.iter session.Store | ||
do! session.AsyncSaveChanges() | ||
return merged | ||
else | ||
return upcast stillGood | ||
} | ||
|
||
interface EveLib.FSharp.IEveQueries with | ||
member x.GetItemIds([<ParamArray>] names : string[]) = getItemIds names | ||
member x.GetItemNames([<ParamArray>] ids : int[]) = getItemNames ids | ||
interface EveLib.Async.IEveQueries with | ||
member x.GetItemIds([<ParamArray>] names : string[]) = getItemIds names |> Async.StartAsTask | ||
member x.GetItemNames([<ParamArray>] ids : int[]) = getItemNames ids |> Async.StartAsTask | ||
interface EveLib.Sync.IEveQueries with | ||
member x.GetItemIds([<ParamArray>] names : string[]) = getItemIds names |> Async.RunSynchronously | ||
member x.GetItemNames([<ParamArray>] ids : int[]) = getItemNames ids |> Async.RunSynchronously |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
namespace EveLib.RavenCache | ||
|
||
open System | ||
open Raven.Client | ||
open Raven.Client.Linq | ||
open EveLib | ||
|
||
type internal MapQueries(baseClient: FSharp.IMapQueries, store: IDocumentStore) = | ||
|
||
// TODO: this crashes RavenDB with a Stack Overflow Exception | ||
let getRecentKills () = async { | ||
use session = store.OpenAsyncSession() | ||
|
||
let! kills = session.Query<RecentKills>() |> AsyncQuery.head | ||
|
||
match kills with | ||
| None -> | ||
let! updated = baseClient.GetRecentKills() | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
| Some k when k.CachedUntil < DateTimeOffset.UtcNow -> | ||
let! updated = baseClient.GetRecentKills() | ||
session.Delete(k) | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
| Some k -> | ||
return k | ||
} | ||
|
||
interface EveLib.FSharp.IMapQueries with | ||
member x.GetRecentKills() = getRecentKills() | ||
interface EveLib.Async.IMapQueries with | ||
member x.GetRecentKills() = getRecentKills() |> Async.StartAsTask | ||
interface EveLib.Sync.IMapQueries with | ||
member x.GetRecentKills() = getRecentKills() |> Async.RunSynchronously |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
namespace EveLib.RavenCache | ||
|
||
open System | ||
open Raven.Client | ||
open Raven.Client.Linq | ||
open EveLib | ||
|
||
type RavenEveClient(apiKey:ApiKey) = | ||
|
||
static let store = Document.DocumentStore.OpenInitializedStore() | ||
|
||
let baseClient = EveClient.CreateFSharp apiKey | ||
let character = lazy( CharacterQueries(baseClient.Character, store) ) | ||
let corporation = lazy( CorporationQueries(baseClient.Corporation, store) ) | ||
let eve = lazy( EveQueries(baseClient.Eve, store) ) | ||
let map = lazy( MapQueries(baseClient.Map, store) ) | ||
|
||
let getCharacters () = async { | ||
use session = store.OpenAsyncSession() | ||
|
||
let! charList = | ||
query { | ||
for cl in session.Query<CharacterList>() do | ||
where (cl.KeyId = apiKey.Id) | ||
select cl | ||
take 1 | ||
} |> AsyncQuery.head | ||
|
||
match charList with | ||
| None -> | ||
let! updated = baseClient.GetCharacters() | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
| Some cl when cl.CachedUntil < DateTimeOffset.UtcNow -> | ||
try | ||
let! updated = baseClient.GetCharacters() | ||
session.Delete(cl) | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
with _ -> | ||
return cl | ||
| Some cl -> | ||
return cl | ||
} | ||
|
||
let getServerStatus () = async { | ||
use session = store.OpenAsyncSession() | ||
|
||
let! status = session.Query<ServerStatus>() |> AsyncQuery.head | ||
|
||
match status with | ||
| None -> | ||
let! updated = baseClient.GetServerStatus() | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
| Some st when st.CachedUntil < DateTimeOffset.UtcNow -> | ||
try | ||
let! updated = baseClient.GetServerStatus() | ||
session.Delete(st) | ||
session.Store(updated) | ||
do! session.AsyncSaveChanges() | ||
return updated | ||
with _ -> | ||
return st | ||
| Some st -> | ||
return st | ||
} | ||
|
||
interface EveLib.FSharp.IEveClient with | ||
member x.GetCharacters() = getCharacters() | ||
member x.GetServerStatus() = getServerStatus() | ||
member x.Character = upcast character.Value | ||
member x.Corporation = upcast corporation.Value | ||
member x.Eve = upcast eve.Value | ||
member x.Map = upcast map.Value | ||
|
||
interface EveLib.Async.IEveClient with | ||
member x.GetCharacters() = getCharacters() |> Async.StartAsTask | ||
member x.GetServerStatus() = getServerStatus() |> Async.StartAsTask | ||
member x.Character = upcast character.Value | ||
member x.Corporation = upcast corporation.Value | ||
member x.Eve = upcast eve.Value | ||
member x.Map = upcast map.Value | ||
|
||
interface EveLib.Sync.IEveClient with | ||
member x.GetCharacters() = getCharacters() |> Async.RunSynchronously | ||
member x.GetServerStatus() = getServerStatus() |> Async.RunSynchronously | ||
member x.Character = upcast character.Value | ||
member x.Corporation = upcast corporation.Value | ||
member x.Eve = upcast eve.Value | ||
member x.Map = upcast map.Value | ||
|
||
static member CreateFSharp apiKey store = RavenEveClient(apiKey) :> EveLib.FSharp.IEveClient | ||
static member CreateAsync apiKey store = RavenEveClient(apiKey) :> EveLib.Async.IEveClient | ||
static member CreateSync apiKey = RavenEveClient(apiKey) :> EveLib.Sync.IEveClient |
Oops, something went wrong.