-
Notifications
You must be signed in to change notification settings - Fork 282
/
Service_Net.re
91 lines (79 loc) · 2.43 KB
/
Service_Net.re
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
open Oni_Core;
module Log = (val Log.withNamespace("Oni2.Service.Net"));
module Internal = {
let getTemporaryFilePath = () => {
open Base.Result.Let_syntax;
// TODO: De-syncify
let ret = {
let%bind tempDir = Luv.Path.tmpdir();
let%bind (tempFile, _) =
Luv.File.Sync.mkstemp(tempDir ++ "/oni2-download-XXXXXX");
Ok(tempFile);
};
ret |> Result.map_error(Luv.Error.strerror);
};
};
module Cache = {
let cache = Hashtbl.create(32);
let check = (url: string) => {
let ret = Hashtbl.find_opt(cache, url);
switch (ret) {
| None => Log.tracef(m => m("Cache miss: %s", url))
| Some(_) => Log.tracef(m => m("Cache hit: %s", url))
};
ret;
};
let add = (~url: string, dest: string) => {
Log.tracef(m => m("Adding cache entry: %s -> %s", url, dest));
Hashtbl.add(cache, url, dest);
};
};
module Request = {
let json = (~setup, ~decoder: Json.decoder('a), url) => {
let promise = NodeTask.run(~args=[url], ~setup, "request.js");
Lwt.bind(
promise,
(output: string) => {
let result: result('a, string) =
output
|> Yojson.Safe.from_string
|> Json.Decode.decode_value(decoder)
|> Result.map_error(Json.Decode.string_of_error);
switch (result) {
| Ok(v) => Lwt.return(v)
| Error(msg) => Lwt.fail_with(msg)
};
},
);
};
let download = (~dest=?, ~setup, url) => {
let run = maybeDest => {
let destResult =
switch (maybeDest) {
| None => Internal.getTemporaryFilePath()
| Some(path) => Ok(path)
};
switch (destResult) {
| Error(msg) => Lwt.fail_with(msg)
| Ok(dest) =>
NodeTask.run(~args=[url, dest], ~setup, "download.js")
|> Lwt.map(_ => {
Cache.add(~url, dest);
dest;
})
};
};
let maybeCacheResult = Cache.check(url);
switch (maybeCacheResult, dest) {
// There was a result cached, and dest was not specified - return cached dest
| (Some(cachedDest), None) => Lwt.return(cachedDest)
// There was a result cached, and a dest was specified... We don't need
// a request, we can just copy locally.
| (Some(cachedDest), Some(dest)) =>
Service_OS.Api.copy(~source=cachedDest, ~target=dest, ~overwrite=true)
|> Lwt.map(_ => dest)
// No cache result - run the request
| (None, maybeDest) => run(maybeDest)
};
};
};