This repository has been archived by the owner on Jun 7, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.fs
96 lines (77 loc) · 2.55 KB
/
Program.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
open FSharp.Control.Tasks
open Giraffe
open Saturn
open Saturn.Endpoint.Router
open Microsoft.AspNetCore.Http
open System
open System.IO
open System.Text.Json
open FSharp.Control.Reactive
type INotifierService =
inherit IDisposable
abstract OnFileChanged : IObservable<string>
let getNotifier (path: string) : INotifierService =
let fsw = new FileSystemWatcher(path)
fsw.NotifyFilter <- NotifyFilters.FileName ||| NotifyFilters.Size
fsw.EnableRaisingEvents <- true
let changed =
fsw.Changed
|> Observable.map (fun args -> args.Name)
let deleted =
fsw.Deleted
|> Observable.map (fun args -> args.Name)
let renamed =
fsw.Renamed
|> Observable.map (fun args -> args.Name)
let created =
fsw.Created
|> Observable.map (fun args -> args.Name)
let obs =
Observable.mergeSeq [ changed
deleted
renamed
created ]
{ new INotifierService with
override _.Dispose() : unit = fsw.Dispose()
override _.OnFileChanged: IObservable<string> = obs }
let sse next (ctx: HttpContext) =
task {
let res = ctx.Response
ctx.SetStatusCode 200
ctx.SetHttpHeader("Content-Type", "text/event-stream")
ctx.SetHttpHeader("Cache-Control", "no-cache")
let notifier = getNotifier @"C:\Users\scyth\Desktop"
let onFileChanged =
notifier.OnFileChanged
|> Observable.subscribe
(fun filename ->
task {
let data =
JsonSerializer.Serialize({| filename = filename |})
do! res.WriteAsync $"event:reload\ndata:{data}\n\n"
do! res.Body.FlushAsync()
}
|> Async.AwaitTask
|> Async.StartImmediate)
do! res.WriteAsync($"id:{ctx.Connection.Id}\nevent:start\ndata:{DateTime.Now}\n\n")
do! res.Body.FlushAsync()
ctx.RequestAborted.Register
(fun _ ->
notifier.Dispose()
onFileChanged.Dispose())
|> ignore
while true do
do! Async.Sleep(TimeSpan.FromSeconds 1.)
return! text "" next ctx
}
// you can add as many SSE endpoints as you want!
let appRouter = router { get "/sse" sse }
[<EntryPoint>]
let main args =
let app =
application {
use_endpoint_router appRouter
use_static "wwwroot"
}
run app
0