Created
September 3, 2020 02:58
-
-
Save altbodhi/bbc5da07654921ded8fe151d7bcd6384 to your computer and use it in GitHub Desktop.
Прототип новой функциональности на F# глазами C#-программиста
This file contains hidden or 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
| open System | |
| open System.Threading | |
| let rnd = Random(Environment.TickCount) | |
| let disks = [ 1; 2; 3; 4 ] | |
| type Status = | |
| | Fail of int | |
| | Normal of int | |
| type LastSend = int * DateTime | |
| let getStatus d = | |
| if rnd.Next(100) < 50 then Fail d else Normal d | |
| let reSendAfter = DateTime.Now.AddSeconds(70.) | |
| let createTimerAndObservable timerInterval (stopAfter: int) = | |
| let timer = | |
| new System.Timers.Timer(float timerInterval) | |
| timer.AutoReset <- true | |
| let observable = timer.Elapsed | |
| let task = | |
| async { | |
| timer.Start() | |
| do! Async.Sleep stopAfter | |
| timer.Stop() | |
| } | |
| (task, observable) | |
| let timer, timerEventStream = createTimerAndObservable 5000 60000 | |
| let sendMessage s = printfn "%s" s | |
| let diskAgent = | |
| MailboxProcessor<Status> | |
| .Start(fun inbox -> | |
| let rec messageLoop (lastChecks) = | |
| async { | |
| let! msg = inbox.Receive() | |
| match msg with | |
| | Fail d -> | |
| if lastChecks | |
| |> List.exists (fun (disk, time) -> disk = d && time < reSendAfter) then | |
| printfn "Disk %d is fail. Skip send message" d | |
| else | |
| sprintf "Disk %d is fail. Required replacement." d | |
| |> sendMessage | |
| return! messageLoop | |
| (lastChecks | |
| |> List.filter (fun (disk, _) -> disk <> d) | |
| |> List.append [ (d, DateTime.Now) ]) | |
| | Normal d -> | |
| printfn "Disk %d is normal" d | |
| return! messageLoop | |
| (lastChecks | |
| |> List.filter (fun (disk, _) -> disk <> d)) | |
| } | |
| messageLoop ([])) | |
| timerEventStream | |
| |> Observable.subscribe (fun _ -> | |
| printfn "%A check disks status" DateTime.Now | |
| for d in disks do | |
| getStatus d |> diskAgent.Post) | |
| Async.RunSynchronously timer |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Идея в том, что сообщение о сбое диска должно быть отправлено один раз до наступления некоторого времени.