Est-ce que quelqu'un sait de « l'art antérieur » en ce qui concerne le sujet suivant:Lazy .. mais les données avides chargeur dans F #
- J'ai des données qui prennent un peu de temps décent pour charger. ils sont au niveau historique pour divers stocks.
- Je voudrais les précharger en quelque sorte, pour éviter le temps d'attente lors de l'utilisation de mon application
- Cependant, les préchargement en un seul morceau au début fait mon application ne répond d'abord qui n'est pas facile à utiliser
donc je comme pas charger mes données .... sauf si l'utilisateur n'en demande pas et joue avec ce qu'il a déjà, auquel cas je voudrais obtenir petit à petit. Donc, ce n'est ni «paresseux» ni «avide», plus «paresseux quand vous en avez besoin» et «avide quand vous le pouvez», d'où l'acronyme LWYNEWYC.
J'ai fait ce qui suit qui semble fonctionner, mais je me demande simplement s'il existe une approche reconnue et bénie pour une telle chose?
let r = LoggingFakeRepo() :> IQuoteRepository
r.getHisto "1" |> ignore //prints Getting histo for 1 when called
let rc = RepoCached (r) :> IQuoteRepository
rc.getHisto "1" |> ignore //prints Getting histo for 1 the first time only
let rcc = RepoCachedEager (r) :> IQuoteRepository
rcc.getHisto "100" |> ignore //prints Getting histo 1..100 by itself BUT
//prints Getting histo 100 immediately when called
Et les classes
type IQuoteRepository =
abstract getUnderlyings : string seq
abstract getHisto : string -> string
type LoggingFakeRepo() =
interface IQuoteRepository with
member x.getUnderlyings = printfn "getting underlyings"
[1 .. 100] |> List.map string :> _
member x.getHisto udl = printfn "getting histo for %A" udl
"I am a historical dataset in a disguised party"
type RepoCached (rep : IQuoteRepository) =
let memoize f =
let cache = new System.Collections.Generic.Dictionary<_, _>()
fun x ->
if cache.ContainsKey(x) then cache.[x]
else let res = f x
cache.[x] <- res
res
let udls = lazy (rep.getUnderlyings)
let gethistom = memoize rep.getHisto
interface IQuoteRepository with
member x.getUnderlyings = udls.Force()
member x.getHisto udl = gethistom udl
type Message = string * AsyncReplyChannel<UnderlyingWrap>
type RepoCachedEager (rep : IQuoteRepository) =
let udls = rep.getUnderlyings
let agent = MailboxProcessor<Message>.Start(fun inbox ->
let repocached = RepoCached (rep) :> IQuoteRepository
let rec loop l =
async { try
let timeout = if l|> List.isEmpty then -1 else 50
let! (udl, replyChannel) = inbox.Receive(timeout)
replyChannel.Reply(repocached.getHisto udl)
do! loop l
with
| :? System.TimeoutException ->
let udl::xs = l
repocached.getHisto udl |> ignore
do! loop xs
}
loop (udls |> Seq.toList))
interface IQuoteRepository with
member x.getUnderlyings = udls
member x.getHisto udl = agent.PostAndReply(fun reply -> udl, reply)
+1 Je pense que votre solution est déjà plutôt sympa! Ajoutons quelques idées dans une réponse ... –