f# - Akka.Net 关闭不等待 Serilog?
问题描述
我有以下代码,我必须添加Threading.Thread.Sleep 5000
等待五秒钟才能关闭演员系统。否则,一些写入数据库的 Serilog 日志将不会保存。有没有办法确保在退出程序之前完成所有日志记录?
open System
open Akka.FSharp
open Akka
type CRange = CRange of low: string * high: string
type ErrorMessage = string
type CError =
| LoginFailed of string // Optional reason
| CTimeOut of CRange list // new range
| CException of CRange list * exn
| CMessage of CRange list * ErrorMessage
type CTask =
CTask of
c: string *
username: string *
password: string *
proxyAddress: string *
cycle: DateTime *
issuerRange: CRange list *
filterTable: bool
type DoWork = Map<string, CTask -> Result<int * string, CError>>
type PartKeyCount = PartKeyCount of Key: string * Count: int
type PartGroupCount = PartGroupCount of Group: string list * Count: int
let system = System.create "ASystem" <| Configuration.load ()
let scheduler (actors: Actor.IActorRef list) task (mailbox: Actor<Result<int, CError>>) =
let newTask task range =
let (CTask(c, username, password, proxy, cycle, _, filter)) = task
CTask(c, username, password, proxy, cycle, range, filter)
let rec loop (list: CRange list list) running = actor {
let akkaName = mailbox.Self.Path.Name
printfn "%s scheduler loop (Running: %d Todo:%d)" akkaName running list.Length
let! m = mailbox.Receive ()
let sender = mailbox.Sender ()
printfn "%s received message %A from %A" akkaName m sender
match m with
| Ok _ ->
printfn "finished one"
match list with
| [] ->
if running = 1 then
//Log.Information("....")
Threading.Thread.Sleep 5000 // Wait for 5 seconds
mailbox.Context.System.Terminate() |> ignore
else
return! loop [] (running - 1)
| x :: xs ->
printfn "Finished one. Todo %d, running %d - %A. New task %A to %A" xs.Length running sender x sender
let t = newTask task x
sender.Tell(t, mailbox.Self) // <!
return! loop xs running
| _ -> ()
}
let groups = [(CRange ("A","A"), 1); (CRange ("B","B"), 1); (CRange ("C","C"), 1);
(CRange ("D","D"), 1); (CRange ("zzz","zzz"), 1)]
let n = if actors.Length < groups.Length then actors.Length else groups.Length
[0..n-1] |> List.iter(fun i ->
let t = newTask task [fst groups.[i]]
actors.[i].Tell(t, mailbox.Self))
let todo = groups |> Seq.skip n |> Seq.toList |> List.map(fun (x, _) -> [x])
Console.WriteLine("Groups {0}; Running {1}; Todo: {2}", groups.Length, n, todo.Length)
loop todo n
let processor (mailbox: Actor<CTask>) =
let rec loop () = actor {
let! m = mailbox.Receive ()
let sender = mailbox.Sender ()
let akkaName = mailbox.Self.Path.Name
printfn "* %s received message %A from %A" akkaName m sender
sender <! (Ok DateTime.Now.Millisecond :> Result<int, CError>)
printfn "* %s sent to %A." akkaName sender
return! loop()
}
loop ()
let spawnSystems n =
[1..n]
|> List.map(fun i ->
spawn system (sprintf "Processor%d" i) (processor)
)
let startAkka task actorNumber =
let actors = spawnSystems actorNumber
Threading.Thread.Sleep 1000
scheduler actors task
|> spawn system "Scheduler"
|> ignore
system.WhenTerminated.Wait()
[<EntryPoint>]
let main argv =
let c = "priv"
let cycle = new DateTime(2020, 1, 1)
let username, password = "username", "password"
let task = CTask(c, username, password, "", cycle, [], false)
startAkka task 2
0
解决方案
在关闭 Akka.net actor 系统之前,您需要告诉 Serilog “刷新”任何缓冲的消息。根据您使用 Serilog 的方式,有不同的方法可以做到这一点。
使用 Serilog 最简单的方法是通过全局Log
类:
Log.Logger = new LoggerConfiguration()
.WriteTo.File(@"myapp\log.txt")
.CreateLogger();
Log.Information("Hello!");
// Your application runs, then:
Log.CloseAndFlush();
如果不使用静态Log
类,您将使用它LoggerConfiguration
来创建ILogger
和处置该实例。
using (var log = new LoggerConfiguration()
.WriteTo.File(@"myapp\log.txt")
.CreateLogger())
{
log.Information("Hello again!");
// Your app runs, then disposal of `log` flushes any buffers
}
您可以查看有关Loggers 生命周期的更多详细信息。
推荐阅读
- javascript - 获取第一个数组中具有 id 的对象与 java 脚本中其他数组的对象中的 id 相同
- ios - 上下文闭包类型 '(Any?) -> Void' 需要 1 个参数,但在闭包体中使用了 2 个
- javascript - 使用 Crossfilter 如何返回特定类型的所有 id 值的数组
- ios - 从 swift cocoa touch 框架导入 jwt
- python-3.x - 为什么我无法连接到数据库
- react-native-navigation - react-native-navigation v2中左侧菜单右侧的阴影去掉?
- c# - 如何使用 C# Fluent 在 SQL 中插入汉字
- ruby-on-rails - Rspec ruby on rails:Haversine gem 在编写单元测试时返回 nil 值
- julia - 错误:LoadError:UndefVarError:TCPServer 未定义 Julia
- google-cloud-platform - Dataflow 停止流式传输到 BigQuery 且没有错误