Skip to content

Commit 6c0bcb6

Browse files
panagosg7meta-codesync[bot]
authored andcommitted
[flow] Back out D104362011 (restart server on flowconfig/package.json changes)
Summary: D104362011 changed the monitor's response to `Flowconfig_changed` from "exit along with the server" to "respawn the server in-place". The respawned server comes up in lazy mode, so a subsequent CI `flow status --lazy-mode none` connects to it and never runs a full check — D105744590 (`[react-native-view-shot] Upgrade to 5.1.0`) landed this way. Back out the entirety of D104362011 except for the `experimental.restart_on_flowconfig_change` config option, which is kept as a parsed-but-inert option so flowconfigs that set it (per D105897416) continue to validate after this binary is released. Changelog: [internal] Reviewed By: SamChou19815 Differential Revision: D105899555 fbshipit-source-id: 9d3dfc828a92da4253f868a7a5497189cff69bec
1 parent 9f058fa commit 6c0bcb6

21 files changed

Lines changed: 39 additions & 217 deletions

File tree

rust_port/crates/flow_cli/src/command_utils.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,7 +2109,6 @@ pub(super) fn make_options(
21092109
relay_integration_excludes,
21102110
relay_integration_module_prefix,
21112111
relay_integration_module_prefix_includes,
2112-
restart_on_flowconfig_change,
21132112
root_name,
21142113
saved_state_direct_serialization,
21152114
saved_state_parallel_decompress,
@@ -2755,7 +2754,6 @@ pub(super) fn make_options(
27552754
relay_integration_excludes,
27562755
relay_integration_module_prefix: relay_integration_module_prefix.map(FlowSmolStr::new),
27572756
relay_integration_module_prefix_includes,
2758-
restart_on_flowconfig_change,
27592757
root: Arc::new(root),
27602758
root_name: root_name.map(FlowSmolStr::new),
27612759
saved_state_direct_serialization,

rust_port/crates/flow_common/src/options.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ pub struct Options {
248248
pub relay_integration_excludes: Arc<[Regex]>,
249249
pub relay_integration_module_prefix: Option<FlowSmolStr>,
250250
pub relay_integration_module_prefix_includes: Arc<[Regex]>,
251-
pub restart_on_flowconfig_change: bool,
252251
pub root: Arc<PathBuf>,
253252
pub root_name: Option<FlowSmolStr>,
254253
pub saved_state_direct_serialization: bool,

rust_port/crates/flow_common_exit_status/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub enum FlowExitStatus {
3333
NoServerRunning,
3434
// Ran out of retries
3535
OutOfRetries,
36-
// Invalid .flowconfig (parse error, version mismatch). Fatal — monitor exits.
36+
// Invalid .flowconfig
3737
InvalidFlowconfig,
3838
// Provided path is not a file as required
3939
PathIsNotAFile,
@@ -52,7 +52,7 @@ pub enum FlowExitStatus {
5252
ServerOutOfDate,
5353
// When the shared memory is missing space (e.g. full /dev/shm)
5454
OutOfSharedMemory,
55-
// The .flowconfig or package.json changed at runtime. Monitor restarts the server.
55+
// The .flowconfig has changed and we're out of date
5656
FlowconfigChanged,
5757
// Failed to parse the command line or misuse of command line arguments
5858
CommandlineUsageError,

rust_port/crates/flow_config/src/flowconfig.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ pub mod opts {
185185
pub relay_integration_excludes: Vec<String>,
186186
pub relay_integration_module_prefix: Option<String>,
187187
pub relay_integration_module_prefix_includes: Vec<String>,
188-
pub restart_on_flowconfig_change: bool,
189188
pub root_name: Option<String>,
190189
pub saved_state_direct_serialization: bool,
191190
pub saved_state_parallel_decompress: bool,
@@ -348,7 +347,6 @@ pub mod opts {
348347
relay_integration_module_prefix_includes: vec![ocaml_str_to_rust_regex(
349348
"<PROJECT_ROOT>/.*",
350349
)],
351-
restart_on_flowconfig_change: true,
352350
root_name: None,
353351
saved_state_direct_serialization: false,
354352
saved_state_parallel_decompress: false,
@@ -2179,6 +2177,7 @@ pub mod opts {
21792177
"experimental.projects_path_mapping",
21802178
"experimental.records",
21812179
"experimental.records.includes",
2180+
"experimental.restart_on_flowconfig_change",
21822181
"experimental.strict_es6_import_export",
21832182
"experimental.ts_syntax",
21842183
"experimental.allow_variance_keywords",
@@ -2549,14 +2548,12 @@ pub mod opts {
25492548
config,
25502549
))
25512550
}
2552-
"experimental.restart_on_flowconfig_change" => Some(parse_boolean(
2553-
|opts, v| {
2554-
opts.restart_on_flowconfig_change = v;
2555-
Ok(())
2556-
},
2557-
values,
2558-
config,
2559-
)),
2551+
// Parsed for backwards compatibility with flowconfigs that still set
2552+
// `experimental.restart_on_flowconfig_change`. Has no runtime effect;
2553+
// kept so those flowconfigs do not error out.
2554+
"experimental.restart_on_flowconfig_change" => {
2555+
Some(parse_boolean(|_, _| Ok(()), values, config))
2556+
}
25602557
"experimental.strict_es6_import_export" => {
25612558
Some(strict_es6_import_export_parser(values, config))
25622559
}

rust_port/crates/flow_server_monitor/src/flow_server_monitor_server.rs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -996,8 +996,6 @@ mod keep_alive_loop {
996996
if monitor_options.no_restart {
997997
return (true, None, false);
998998
}
999-
let restart_on_flowconfig_change =
1000-
monitor_options.server_options.restart_on_flowconfig_change;
1001999
use flow_common_exit_status::FlowExitStatus;
10021000
match exit_status {
10031001
//*** Things the server might exit with that implies that the monitor should exit too ***
@@ -1009,6 +1007,8 @@ mod keep_alive_loop {
10091007
// Parse/version/etc error. Server will never start correctly.
10101008
| FlowExitStatus::PathIsNotAFile
10111009
// Required a file but privided path was not a file
1010+
| FlowExitStatus::FlowconfigChanged
1011+
// We could survive some config changes, but it's too hard to tell
10121012
| FlowExitStatus::InvalidSavedState
10131013
// The saved state file won't automatically recover by restarting
10141014
| FlowExitStatus::UnusedServer
@@ -1055,13 +1055,7 @@ mod keep_alive_loop {
10551055
false,
10561056
),
10571057
FlowExitStatus::KilledByMonitor /* The server died because we asked it to die */ => (false, None, false),
1058-
FlowExitStatus::FlowconfigChanged if !restart_on_flowconfig_change => {
1059-
// Killswitch: revert to the legacy behavior where the monitor exits on
1060-
// flowconfig/package.json changes. Remove once the new behavior is fully rolled out.
1061-
(true, None, false)
1062-
}
1063-
FlowExitStatus::Restart /* The server asked to be restarted */
1064-
| FlowExitStatus::FlowconfigChanged /* .flowconfig or package.json changed; restart with new config */ => (
1058+
FlowExitStatus::Restart /* The server asked to be restarted */ => (
10651059
false,
10661060
Some(flow_server_env::server_status::RestartReason::Restart),
10671061
false,
@@ -1095,12 +1089,10 @@ mod keep_alive_loop {
10951089
let msg = flow_server_env::lsp_prot::MessageFromServer::NotificationFromServer(
10961090
flow_server_env::lsp_prot::NotificationFromServer::ServerExit(exit_type),
10971091
);
1098-
// Atomically write the ServerExit notification then close. Going through
1099-
// `WriteAndClose` keeps wire ordering correct: the command loop drains the
1100-
// write before the close fires. Using `write` + `try_flush_and_close` would
1101-
// race — `try_flush_and_close` aborts the read loop, whose catch handler
1102-
// closes the socket before the queued write reaches the wire.
1103-
conn.write_and_close(msg);
1092+
// it's ok if the stream is already closed, we must be shutting down already
1093+
conn.write(msg);
1094+
// it's also ok if the flush fails because the socket is already closed
1095+
conn.try_flush_and_close();
11041096
}
11051097
}
11061098

rust_port/crates/flow_server_monitor/src/socket_acceptor.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -196,22 +196,8 @@ fn create_persistent_connection(
196196

197197
Server::notify_new_persistent_connection(client_id, lsp_init_params);
198198

199-
// Hold a clone of the underlying TCP stream so the close callback can
200-
// shut it down. The outer `close` from `socket_acceptor_loop` was disarmed
201-
// when we accepted the persistent client, so on its own it no longer
202-
// closes the wire — and the LSP would never see EOF. Shutting down here
203-
// sends FIN to the LSP, which is what triggers its disconnect handling.
204-
let shutdown_slot = std::sync::Arc::new(std::sync::Mutex::new(Some(
205-
client_stream
206-
.try_clone()
207-
.expect("clone of TcpStream for persistent shutdown failed"),
208-
)));
209-
210199
let outer_close = close;
211200
let close: Arc<dyn Fn() + Send + Sync> = Arc::new(move || {
212-
if let Some(s) = shutdown_slot.lock().unwrap().take() {
213-
self::close(s);
214-
}
215201
Server::notify_dead_persistent_connection(client_id);
216202
outer_close();
217203
});

rust_port/crates/flow_server_rechecker/src/recheck_updates.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,7 @@ fn get_updated_flowconfig(config_path: &str) -> Result<(FlowConfig, String), Err
9191
}
9292
}
9393

94-
fn assert_compatible_flowconfig_version(
95-
options: &Options,
96-
config: &FlowConfig,
97-
) -> Result<(), Error> {
94+
fn assert_compatible_flowconfig_version(config: &FlowConfig) -> Result<(), Error> {
9895
let not_satisfied = |version_constraint: &str| -> bool {
9996
match semver::satisfies(Some(true), version_constraint, flow_version::version()) {
10097
Ok(result) => !result,
@@ -108,14 +105,10 @@ fn assert_compatible_flowconfig_version(
108105
version_constraint,
109106
flow_version::version(),
110107
);
111-
// Killswitch: under the legacy behavior, version mismatches surfaced as
112-
// FlowconfigChanged (exit code 16). Remove once the new behavior is fully rolled out.
113-
let exit_status = if options.restart_on_flowconfig_change {
114-
FlowExitStatus::InvalidFlowconfig
115-
} else {
116-
FlowExitStatus::FlowconfigChanged
117-
};
118-
Err(Error::Unrecoverable { msg, exit_status })
108+
Err(Error::Unrecoverable {
109+
msg,
110+
exit_status: FlowExitStatus::FlowconfigChanged,
111+
})
119112
}
120113
_ => Ok(()),
121114
}
@@ -131,7 +124,7 @@ fn assert_compatible_flowconfig_change(options: &Options, config_path: &str) ->
131124
".flowconfig changed (hash {} -> {}); server must restart",
132125
old_hash, new_hash
133126
);
134-
assert_compatible_flowconfig_version(options, &new_config)?;
127+
assert_compatible_flowconfig_version(&new_config)?;
135128
Err(Error::Unrecoverable {
136129
msg,
137130
exit_status: FlowExitStatus::FlowconfigChanged,

src/commands/commandUtils.ml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,6 @@ let make_options
16891689
~f:(fun pattern ->
16901690
pattern |> Files.expand_project_root_token_as_absolute ~root |> Str.regexp)
16911691
(FlowConfig.relay_integration_module_prefix_includes flowconfig);
1692-
opt_restart_on_flowconfig_change = FlowConfig.restart_on_flowconfig_change flowconfig;
16931692
opt_root = root;
16941693
opt_root_name = FlowConfig.root_name flowconfig;
16951694
opt_saved_state_fetcher;

src/commands/config/flowConfig.ml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ module Opts = struct
153153
relay_integration_excludes: string list;
154154
relay_integration_module_prefix: string option;
155155
relay_integration_module_prefix_includes: string list;
156-
restart_on_flowconfig_change: bool;
157156
root_name: string option;
158157
saved_state_fetcher: Options.saved_state_fetcher;
159158
saved_state_direct_serialization: bool;
@@ -324,7 +323,6 @@ module Opts = struct
324323
relay_integration_excludes = [];
325324
relay_integration_module_prefix = None;
326325
relay_integration_module_prefix_includes = ["<PROJECT_ROOT>/.*"];
327-
restart_on_flowconfig_change = true;
328326
root_name = None;
329327
saved_state_fetcher = Options.Dummy_fetcher;
330328
saved_state_direct_serialization = false;
@@ -1240,9 +1238,10 @@ module Opts = struct
12401238
~multiple:true
12411239
(fun opts v -> Ok { opts with records_includes = v :: opts.records_includes })
12421240
);
1243-
( "experimental.restart_on_flowconfig_change",
1244-
boolean (fun opts v -> Ok { opts with restart_on_flowconfig_change = v })
1245-
);
1241+
(* Parsed for backwards compatibility with flowconfigs that still set
1242+
[experimental.restart_on_flowconfig_change]. Has no runtime effect;
1243+
kept so those flowconfigs do not error out. *)
1244+
("experimental.restart_on_flowconfig_change", boolean (fun opts _ -> Ok opts));
12461245
("experimental.strict_es6_import_export", strict_es6_import_export_parser);
12471246
("experimental.ts_syntax", boolean (fun opts v -> Ok { opts with ts_syntax = v }));
12481247
( "experimental.allow_variance_keywords",
@@ -2245,8 +2244,6 @@ let relay_integration_module_prefix_includes c =
22452244

22462245
let required_version c = c.version
22472246

2248-
let restart_on_flowconfig_change c = c.options.Opts.restart_on_flowconfig_change
2249-
22502247
let root_name c = c.options.Opts.root_name
22512248

22522249
let saved_state_fetcher c = c.options.Opts.saved_state_fetcher

src/commands/config/flowConfig.mli

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,6 @@ val relay_integration_module_prefix_includes : config -> string list
287287

288288
val required_version : config -> string option
289289

290-
val restart_on_flowconfig_change : config -> bool
291-
292290
val root_name : config -> string option
293291

294292
val saved_state_fetcher : config -> Options.saved_state_fetcher

0 commit comments

Comments
 (0)