1
1
import api/hex as api
2
+ import api/hex_repo
3
+ import api/signatures
2
4
import backend/config . { type Config }
3
5
import backend/data/hex_read . { type HexRead }
4
6
import backend/index/connect as postgres
@@ -9,9 +11,11 @@ import birl/duration
9
11
import gleam/hexpm . { type Package }
10
12
import gleam/list
11
13
import gleam/order
14
+ import gleam/otp/supervisor
12
15
import gleam/pgo
13
16
import gleam/result
14
17
import gleam/string
18
+ import retrier
15
19
import wisp
16
20
17
21
type State {
@@ -25,20 +29,24 @@ type State {
25
29
)
26
30
}
27
31
28
- pub fn sync_new_gleam_releases ( cnf : Config ) -> Result ( HexRead , Error ) {
32
+ pub fn sync_new_gleam_releases (
33
+ cnf : Config ,
34
+ children : supervisor . Children ( Nil ) ,
35
+ ) -> Result ( HexRead , Error ) {
29
36
let ctx = postgres . connect ( cnf )
30
37
wisp . log_info ( "Syncing new releases from Hex" )
31
38
use limit <- result . try ( index . get_last_hex_date ( ctx . connection ) )
32
- use latest <- result . try (
33
- sync_packages ( State (
39
+ use latest <- result . try ( sync_packages (
40
+ State (
34
41
page : 1 ,
35
42
limit : limit ,
36
43
newest : limit ,
37
44
hex_api_key : cnf . hex_api_key ,
38
45
last_logged : birl . now ( ) ,
39
46
db : ctx . connection ,
40
- ) ) ,
41
- )
47
+ ) ,
48
+ children ,
49
+ ) )
42
50
let latest = index . upsert_most_recent_hex_timestamp ( ctx . connection , latest )
43
51
wisp . log_info ( "\n Up to date!" )
44
52
latest
@@ -58,28 +66,42 @@ fn first_timestamp(packages: List(hexpm.Package), state: State) -> Time {
58
66
|> result . unwrap ( state . newest )
59
67
}
60
68
61
- fn sync_packages ( state : State ) -> Result ( Time , Error ) {
69
+ fn sync_packages (
70
+ state : State ,
71
+ children : supervisor . Children ( Nil ) ,
72
+ ) -> Result ( Time , Error ) {
62
73
let page = state . page
63
74
let api_key = state . hex_api_key
64
75
use all_packages <- result . try ( api . get_api_packages_page ( page , api_key ) )
65
76
let state = State ( .. state , newest : first_timestamp ( all_packages , state ) )
66
77
let new_packages = take_fresh_packages ( all_packages , state . limit )
67
- use state <- result . try ( list . try_fold ( new_packages , state , sync_package ) )
78
+ use state <- result . try ( list . try_fold (
79
+ new_packages ,
80
+ state ,
81
+ sync_package ( children ) ,
82
+ ) )
68
83
case list . length ( all_packages ) == list . length ( new_packages ) {
69
84
_ if all_packages == [ ] -> Ok ( state . newest )
70
85
False -> Ok ( state . newest )
71
- True -> sync_packages ( State ( .. state , page : state . page + 1 ) )
86
+ True -> sync_packages ( State ( .. state , page : state . page + 1 ) , children )
72
87
}
73
88
}
74
89
75
- fn sync_package ( state : State , package : hexpm . Package ) -> Result ( State , Error ) {
76
- let secret = state . hex_api_key
77
- use releases <- result . try ( lookup_gleam_releases ( package , secret : secret ) )
78
- case releases {
79
- [ ] -> Ok ( log_if_needed ( state , package . updated_at ) )
80
- _ -> {
81
- use _ <- result . map ( insert_package_and_releases ( package , releases , state ) )
82
- State ( .. state , last_logged : birl . now ( ) )
90
+ fn sync_package ( children : supervisor . Children ( Nil ) ) {
91
+ fn ( state : State , package : hexpm . Package ) -> Result ( State , Error ) {
92
+ let secret = state . hex_api_key
93
+ use releases <- result . try ( lookup_gleam_releases ( package , secret : secret ) )
94
+ case releases {
95
+ [ ] -> Ok ( log_if_needed ( state , package . updated_at ) )
96
+ _ -> {
97
+ use _ <- result . map ( insert_package_and_releases (
98
+ package ,
99
+ releases ,
100
+ state ,
101
+ children ,
102
+ ) )
103
+ State ( .. state , last_logged : birl . now ( ) )
104
+ }
83
105
}
84
106
}
85
107
}
@@ -88,6 +110,7 @@ fn insert_package_and_releases(
88
110
package : hexpm . Package ,
89
111
releases : List ( hexpm . Release ) ,
90
112
state : State ,
113
+ children : supervisor . Children ( Nil ) ,
91
114
) {
92
115
let secret = state . hex_api_key
93
116
let versions =
@@ -100,7 +123,17 @@ fn insert_package_and_releases(
100
123
use owners <- result . try ( api . get_package_owners ( package . name , secret : secret ) )
101
124
use _ <- result . try ( index . sync_package_owners ( state . db , id , owners ) )
102
125
wisp . log_info ( "Saving releases for " <> package . name )
103
- list . try_each ( releases , fn ( r ) { index . upsert_release ( state . db , id , r ) } )
126
+ list . try_each ( releases , fn ( r ) {
127
+ use _ <- result . map ( index . upsert_release ( state . db , id , r ) )
128
+ supervisor . add ( children , {
129
+ use _ <- supervisor . worker ( )
130
+ retrier . retry ( fn ( ) {
131
+ let infos = hex_repo . get_package_infos ( package . name , r . version )
132
+ use # ( package , gleam_toml ) <- result . try ( infos )
133
+ signatures . extract_signatures ( state . db , package , gleam_toml )
134
+ } )
135
+ } )
136
+ } )
104
137
}
105
138
106
139
fn lookup_gleam_releases (
0 commit comments