-
Notifications
You must be signed in to change notification settings - Fork 206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refact: nydusd's state machine #439
Conversation
kicker: &dyn Fn(ApiRequest) -> ApiResponse, | ||
) -> HttpResult { | ||
match (req.method(), req.body.as_ref()) { | ||
(Method::Put, None) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PUT
method in RESTful API design means that the operation can be executed multiple times and always have an idempotent state, is this what the API expects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PUT
method in RESTful API design means that the operation can be executed multiple times and always have an idempotent state, is this what the API expects?
It's expected that daemon in READY is trigger to RUNNING. Just like takeover endpoint with PUT method, it's required for daemon in certain status.
} | ||
|
||
if s == DaemonState::RUNNING { | ||
self.on_event(DaemonStateMachineInput::Stop)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not merge the two events handling if blocks.
They both react on Stop
event
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not merge the two events handling if blocks. They both react on
Stop
event
The INIT
can transfer to DIE
by stop
directly. While the RUNNING
is transferred to DIE
via READY
. For INIT
, there is only one stop
event, instead of two stop
events for RUNNING
.
Please check the patch's changelog, it is somewhat a mess of duplicated messages. Can you squash the SOB lines? |
Good idea! 3q |
0cbb1eb
to
774c6c0
Compare
@@ -289,6 +291,7 @@ lazy_static! { | |||
r.routes.insert(endpoint_v1!("/daemon/events"), Box::new(EventsHandler{})); | |||
r.routes.insert(endpoint_v1!("/daemon/backend"), Box::new(FsBackendInfo{})); | |||
r.routes.insert(endpoint_v1!("/daemon/exit"), Box::new(ExitHandler{})); | |||
r.routes.insert(endpoint_v1!("/daemon/start"), Box::new(StartHandler{})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we relocate the API path to /daemon/fuse/start
since the handler of endpoint /daemon/start
just starts fuse server's service loop. For nydusd itself, it is already started, otherwise how it can handle API requests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we relocate the API path to
/daemon/fuse/start
since the handler of endpoint/daemon/start
just starts fuse server's service loop. For nydusd itself, it is already started, otherwise how it can handle API requests?
The start
endpoint works with status Ready
and RUNNING
, which are designed for only fuse but also for other implements. Maybe run
is more comfortable?
Mount => Running [StartService], | ||
Takeover => Upgrading [Restore], | ||
Exit => Die[StopStateMachine], | ||
Mount => Ready, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems we no longer need Mount
event since nothing is done when migrating state to Ready
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems we no longer need
Mount
event since nothing is done when migrating state to Ready
In fact, we shall do Mount
action. However, it's a bit risky now. Because the Mount content are different in different cases, such as upgrade startup, normal startup, endpoint startup. In total, You're right. There will be abstraction for Mount
action in future.
.map_err(|e| { | ||
DaemonError::WaitDaemon( | ||
*e.downcast::<Error>() | ||
.unwrap_or_else(|e| Box::new(eother!(e))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Um. Hard error conversion path to io::Error
, maybe let WaitDaemon
wrap another type of error message is an easier way. But has nothing to do with this PR.
@@ -477,12 +508,13 @@ pub fn create_nydus_daemon( | |||
inflight_ops: Mutex::new(Vec::new()), | |||
result_receiver: Mutex::new(result_receiver), | |||
trigger: Arc::new(Mutex::new(trigger)), | |||
threads: Mutex::new(Vec::new()), | |||
state_machine_thread: Mutex::new(None), | |||
fuse_service_threads: Mutex::new(Vec::new()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is reaping fuse threads important?
Only wait for state machine termination?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is reaping fuse threads important? Only wait for state machine termination?
Yep, seeking for waiting state machine and fuse service thread termination separately. Because daemon status is only updated after successful action. For example, interrupt
action is executed, then wait fuse service workers done, finally the daemon status is changed from RUNNING
to READY
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
`UPGRADING` and `INTERRUPTED` are designed for hot-upgrading, which is a use case instead of daemon's state. As a result, they are weird in lack of upgrading function. Merge `UPGRADING` and `INTERRUPTED` to `READY`. `READY` means service is well-configured, but waiting for trigger. For fuse-based daemon, it means fuse device is mounted, while fuse mountpoint may be not attached. The daemon lives in `INIT` -> `READY` -> `RUNNING` -> `READY` -> `DIE`. 1. Daemon context with new status. 2. Async `TerminateFuseService`, `Umount` actions. 3. `Start` endpoint, which is usually used after `takeover` endpoint. 4. Async exit after fuse device unmounted abnormally. Signed-off-by: 泰友 <cuichengxu.ccx@antgroup.com>
QUESTION
UPGRADING
andINTERRUPTED
are designed for hot-upgrading, which is a use case instead of daemon's state. As a result, they are weird in lack of upgrading function.DESIGN
Merge
UPGRADING
andINTERRUPTED
toREADY
.READY
means service is well-configured, but waiting for trigger. For fuse-based daemon, it means fuse device is mounted, while fuse mountpoint may be not attached. The daemon lives inINIT
->READY
->RUNNING
->READY
->DIE
.CHANGE
TerminateFuseService
,Umount
actions.Start
endpoint, which is usually used aftertakeover
endpoint.