Skip to content

Commit 1792647

Browse files
committed
state: add lock
1 parent 9a996b3 commit 1792647

File tree

4 files changed

+35
-15
lines changed

4 files changed

+35
-15
lines changed

lib/action.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
100100
let rules = cfg.status_rules.rules in
101101
let action_on_match (branches : branch list) =
102102
let default = Option.to_list cfg.prefix_rules.default_channel in
103-
State.set_repo_pipeline_status ctx.state repo.url ~pipeline ~branches ~status:current_status;
103+
let%lwt () = State.set_repo_pipeline_status ctx.state repo.url ~pipeline ~branches ~status:current_status in
104104
match List.is_empty branches with
105105
| true -> Lwt.return []
106106
| false ->
@@ -118,7 +118,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
118118
)
119119
in
120120
if Context.is_pipeline_allowed ctx repo.url ~pipeline then begin
121-
let repo_state = State.find_or_add_repo ctx.state repo.url in
121+
let%lwt repo_state = State.find_or_add_repo ctx.state repo.url in
122122
match Rule.Status.match_rules ~rules n with
123123
| Some Ignore | None -> Lwt.return []
124124
| Some Allow -> action_on_match n.branches
@@ -261,7 +261,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
261261
let fetch_bot_user_id () =
262262
match%lwt Slack_api.send_auth_test ~ctx () with
263263
| Ok { user_id; _ } ->
264-
ctx.state.bot_user_id <- Some user_id;
264+
State.set_bot_user_id ctx.state user_id;
265265
let%lwt () =
266266
Option.value_map ctx.state_filepath ~default:Lwt.return_unit ~f:(fun path ->
267267
match%lwt State.save ctx.state path with
@@ -298,7 +298,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
298298
)
299299
in
300300
let%lwt bot_user_id =
301-
match ctx.state.bot_user_id with
301+
match State.get_bot_user_id ctx.state with
302302
| Some id -> Lwt.return_some id
303303
| None -> fetch_bot_user_id ()
304304
in

lib/context.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type t = {
1212
state_filepath : string option;
1313
mutable secrets : Config_t.secrets option;
1414
config : Config_t.config Stringtbl.t;
15-
state : State_t.state;
15+
state : State.t;
1616
}
1717

1818
let default_config_filename = "monorobot.json"
@@ -95,7 +95,7 @@ let refresh_state ctx =
9595
match get_local_file path with
9696
| Error e -> fmt_error "error while getting local file: %s\nfailed to get state from file %s" e path
9797
| Ok file ->
98-
let state = State_j.state_of_string file in
98+
let state = { ctx.state with state = State_j.state_of_string file } in
9999
Ok { ctx with state }
100100
end
101101
else Ok ctx

lib/state.ml

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,45 @@ open Base
22
open Common
33
open Devkit
44

5+
type t = {
6+
state : State_t.state;
7+
lock : Lwt_mutex.t;
8+
}
9+
510
let empty_repo_state () : State_t.repo_state = { pipeline_statuses = StringMap.empty }
611

7-
let empty () : State_t.state = { repos = Stringtbl.empty (); bot_user_id = None }
12+
let empty () : t =
13+
let state = State_t.{ repos = Stringtbl.empty (); bot_user_id = None } in
14+
{ state; lock = Lwt_mutex.create () }
15+
16+
let find_or_add_repo' state repo_url = Stringtbl.find_or_add state.State_t.repos repo_url ~default:empty_repo_state
17+
18+
let set_repo_state { state; lock } repo_url repo_state =
19+
Lwt_mutex.with_lock lock @@ fun () ->
20+
Stringtbl.set state.repos ~key:repo_url ~data:repo_state;
21+
Lwt.return_unit
822

9-
let find_or_add_repo (state : State_t.state) repo_url =
10-
Stringtbl.find_or_add state.repos repo_url ~default:empty_repo_state
23+
let find_or_add_repo { state; lock } repo_url =
24+
Lwt_mutex.with_lock lock @@ fun () -> find_or_add_repo' state repo_url |> Lwt.return
1125

12-
let set_repo_pipeline_status (state : State_t.state) repo_url ~pipeline ~(branches : Github_t.branch list) ~status =
26+
let set_repo_pipeline_status { state; lock } repo_url ~pipeline ~(branches : Github_t.branch list) ~status =
1327
let set_branch_status branch_statuses =
1428
let new_statuses = List.map branches ~f:(fun b -> b.name, status) in
1529
let init = Option.value branch_statuses ~default:(Map.empty (module String)) in
1630
List.fold_left new_statuses ~init ~f:(fun m (key, data) -> Map.set m ~key ~data)
1731
in
18-
let repo_state = find_or_add_repo state repo_url in
19-
repo_state.pipeline_statuses <- Map.update repo_state.pipeline_statuses pipeline ~f:set_branch_status
32+
Lwt_mutex.with_lock lock @@ fun () ->
33+
let repo_state = find_or_add_repo' state repo_url in
34+
repo_state.pipeline_statuses <- Map.update repo_state.pipeline_statuses pipeline ~f:set_branch_status;
35+
Lwt.return_unit
36+
37+
let set_bot_user_id { state; _ } user_id = state.State_t.bot_user_id <- Some user_id
38+
39+
let get_bot_user_id { state; _ } = state.State_t.bot_user_id
2040

2141
let log = Log.from "state"
2242

23-
let save state path =
43+
let save { state; _ } path =
2444
let data = State_j.string_of_state state |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in
2545
match write_to_local_file ~data path with
2646
| Ok () -> Lwt.return @@ Ok ()

test/test.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let process ~(secrets : Config_t.secrets) ~config (kind, path, state_path) =
2626
let repo = Github.repo_of_notification @@ Github.parse_exn headers event in
2727
let ctx = Context.make () in
2828
ctx.secrets <- Some secrets;
29-
ignore (State.find_or_add_repo ctx.state repo.url);
29+
let%lwt _ = State.find_or_add_repo ctx.state repo.url in
3030
match state_path with
3131
| None ->
3232
Context.set_repo_config ctx repo.url config;
@@ -38,7 +38,7 @@ let process ~(secrets : Config_t.secrets) ~config (kind, path, state_path) =
3838
Lwt.return ctx
3939
| Ok file ->
4040
let repo_state = State_j.repo_state_of_string file in
41-
Common.Stringtbl.set ctx.state.repos ~key:repo.url ~data:repo_state;
41+
let%lwt () = State.set_repo_state ctx.state repo.url repo_state in
4242
Context.set_repo_config ctx repo.url config;
4343
Lwt.return ctx
4444
in

0 commit comments

Comments
 (0)