Skip to content

Commit 176da86

Browse files
committed
split source file into multiple parts
1 parent 7ecf897 commit 176da86

File tree

3 files changed

+167
-167
lines changed

3 files changed

+167
-167
lines changed

R/internal_call.R

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#' @title Invoke an Analysis Application (Internal Function)
2+
#'
3+
#' @description
4+
#' This internal function executes an analysis application after validating its dependencies.
5+
#' It handles application execution, error reporting, and performance profiling.
6+
#'
7+
#' @param app A list defining the analysis application. Must contain:
8+
#' - `name`: (character) Name of the application (for logging).
9+
#' - `call`: (function) The function to execute the application logic.
10+
#' - `profiler`: (list) Stores performance metrics (e.g., execution time).
11+
#' @param context A list or environment providing runtime context, such as input data paths,
12+
#' environment variables, or configuration settings required by the application.
13+
#'
14+
#' @return Invisibly returns `NULL`. The function primarily updates `app$profiler` with execution
15+
#' time metrics and may modify the `context` during execution.
16+
#'
17+
#' @details
18+
#' ### Key Steps:
19+
#' 1. ​**Dependency Check**:
20+
#' Validates if required context variables and files exist via `check_dependency(app, context)`.
21+
#' - If dependencies are met, proceeds to execute the application.
22+
#' - If dependencies are missing, throws an error with detailed missing resources.
23+
#'
24+
#' 2. ​**Execution**:
25+
#' - Logs start/end timestamps if `options(verbose = TRUE)`.
26+
#' - Executes `app$call` with arguments `app` and `context` using `do.call()`.
27+
#'
28+
#' 3. ​**Error Handling**:
29+
#' - Aggregates missing dependencies into readable error messages.
30+
#' - Calls `throw_err()` to terminate the workflow and report issues.
31+
#'
32+
#' 4. ​**Profiling**:
33+
#' Records total execution time in `app$profiler$time` using `time_span()` for human-readable formatting.
34+
#'
35+
#' @examples
36+
#' \dontrun{
37+
#' # Define a sample application
38+
#' app <- list(
39+
#' name = "demo_analysis",
40+
#' call = function(argv) {
41+
#' print(paste("Running:", argv$app$name))
42+
#' },
43+
#' profiler = list()
44+
#' )
45+
#'
46+
#' # Execute with context
47+
#' .internal_call(app, context = list())
48+
#' }
49+
#'
50+
#' @note
51+
#' - This is an internal function and not intended for direct use.
52+
#' - Error messages include:
53+
#' - Missing context variables (e.g., `dependency$context_env_missing`).
54+
#' - Missing files (e.g., `dependency$workfiles_missing`).
55+
#'
56+
#' @keywords internal
57+
const .internal_call = function(app, context) {
58+
# check of the app dependency
59+
let dependency = check_dependency(app, context);
60+
let t0 = now();
61+
let argv = {
62+
app: app,
63+
context: context
64+
};
65+
let verbose = as.logical(getOption("verbose"));
66+
67+
if (dependency$check) {
68+
if (verbose) {
69+
print(` * exec: ${app$name}...`);
70+
}
71+
72+
# check success, then
73+
# run current data analysis node
74+
do.call(app$call, args = argv);
75+
76+
if (verbose) {
77+
print(`done ~ '${app$name}' ...... ${time_span(now() - t0)}`);
78+
}
79+
} else {
80+
# stop the workflow
81+
const context_err = dependency.context_env_missing(dependency$context);
82+
const file_err = dependency.workfiles_missing(dependency$file);
83+
const msg_err = [
84+
"There are some dependency of current analysis application is not satisfied:",
85+
paste(c("analysis_app:", app$name), sep = " ")
86+
];
87+
88+
throw_err([msg_err, context_err, file_err]);
89+
}
90+
91+
app$profiler = {
92+
time: time_span(now() - t0)
93+
};
94+
95+
invisible(NULL);
96+
}

R/runner.R

Lines changed: 71 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,90 @@
1-
#' @title Invoke an Analysis Application (Internal Function)
1+
2+
#' Internal Workflow Execution Engine
23
#'
34
#' @description
4-
#' This internal function executes an analysis application after validating its dependencies.
5-
#' It handles application execution, error reporting, and performance profiling.
6-
#'
7-
#' @param app A list defining the analysis application. Must contain:
8-
#' - `name`: (character) Name of the application (for logging).
9-
#' - `call`: (function) The function to execute the application logic.
10-
#' - `profiler`: (list) Stores performance metrics (e.g., execution time).
11-
#' @param context A list or environment providing runtime context, such as input data paths,
12-
#' environment variables, or configuration settings required by the application.
13-
#'
14-
#' @return Invisibly returns `NULL`. The function primarily updates `app$profiler` with execution
15-
#' time metrics and may modify the `context` during execution.
5+
#' An internal function that drives the execution of a modular workflow.
6+
#' It sequentially processes analysis modules according to the pipeline
7+
#' configuration while respecting disablement rules.
8+
#'
9+
#' @param context A workflow context object containing:
10+
#' \itemize{
11+
#' \item{pipeline - character vector of module execution order}
12+
#' \item{workflow - list of module definitions}
13+
#' }
14+
#' @param disables A named list specifying module disablement status.
15+
#' Format: `list(module_name = TRUE/FALSE)`. Modules with TRUE will be skipped.
1616
#'
1717
#' @details
18-
#' ### Key Steps:
19-
#' 1. ​**Dependency Check**:
20-
#' Validates if required context variables and files exist via `check_dependency(app, context)`.
21-
#' - If dependencies are met, proceeds to execute the application.
22-
#' - If dependencies are missing, throws an error with detailed missing resources.
23-
#'
24-
#' 2. ​**Execution**:
25-
#' - Logs start/end timestamps if `options(verbose = TRUE)`.
26-
#' - Executes `app$call` with arguments `app` and `context` using `do.call()`.
27-
#'
28-
#' 3. ​**Error Handling**:
29-
#' - Aggregates missing dependencies into readable error messages.
30-
#' - Calls `throw_err()` to terminate the workflow and report issues.
31-
#'
32-
#' 4. ​**Profiling**:
33-
#' Records total execution time in `app$profiler$time` using `time_span()` for human-readable formatting.
34-
#'
35-
#' @examples
36-
#' \dontrun{
37-
#' # Define a sample application
38-
#' app <- list(
39-
#' name = "demo_analysis",
40-
#' call = function(argv) {
41-
#' print(paste("Running:", argv$app$name))
42-
#' },
43-
#' profiler = list()
44-
#' )
45-
#'
46-
#' # Execute with context
47-
#' .internal_call(app, context = list())
18+
#' This function:
19+
#' \enumerate{
20+
#' \item Retrieves module execution order from `context$pipeline`
21+
#' \item Checks disablement status through two mechanisms:
22+
#' \itemize{
23+
#' \item Explicit disablement via `disables` parameter
24+
#' \item Module's own `disable` property (set by upstream modules)
25+
#' }
26+
#' \item Executes non-disabled modules using `.internal_call()`
27+
#' \item Provides verbose logging when `options(verbose=TRUE)`
4828
#' }
4929
#'
30+
#' The workflow context is modified in-place by module execution.
31+
#'
5032
#' @note
51-
#' - This is an internal function and not intended for direct use.
52-
#' - Error messages include:
53-
#' - Missing context variables (e.g., `dependency$context_env_missing`).
54-
#' - Missing files (e.g., `dependency$workfiles_missing`).
33+
#' This is an internal function not meant for direct calling by users.
34+
#' Modules can control subsequent module execution by setting their
35+
#' `disable` property.
5536
#'
37+
#' @return
38+
#' Invisibly returns NULL. Modifies the workflow context object in-place
39+
#' through module executions.
40+
#'
5641
#' @keywords internal
57-
const .internal_call = function(app, context) {
58-
# check of the app dependency
59-
let dependency = check_dependency(app, context);
60-
let t0 = now();
61-
let argv = {
62-
app: app,
63-
context: context
64-
};
42+
#' @seealso \code{\link{.internal_call}} for module execution logic
43+
const __runImpl = function(context, disables = list()) {
44+
let app_pool = context$workflow;
45+
let skip = FALSE;
6546
let verbose = as.logical(getOption("verbose"));
6647

67-
if (dependency$check) {
68-
if (verbose) {
69-
print(` * exec: ${app$name}...`);
48+
if (verbose) {
49+
print("view module configs:");
50+
str(disables);
51+
}
52+
53+
# the pipeline data slot defines the workflow module
54+
# execute sequence.
55+
#
56+
# get a specific workflow analysis app module, and then
57+
# execute the module under a given workflow context
58+
for(let app_name in context$pipeline) {
59+
let app = app_pool[[app_name]];
60+
let skip = FALSE;
61+
62+
if (is.null(app$name)) {
63+
throw_err(`missing app module definition object for '${app_name}', please check of the app function has been hooked or not?`);
7064
}
7165

72-
# check success, then
73-
# run current data analysis node
74-
do.call(app$call, args = argv);
66+
if (app$name in disables) {
67+
if (as.logical(disables[[app$name]])) {
68+
skip = TRUE;
69+
}
70+
} else {
71+
if("disable" in app) {
72+
# current app module may be disable by other
73+
# application from the workflow upsteam
74+
skip = app$disable;
75+
}
76+
}
7577

76-
if (verbose) {
77-
print(`done ~ '${app$name}' ...... ${time_span(now() - t0)}`);
78+
if (!skip) {
79+
.internal_call(app, context);
80+
} else {
81+
if (verbose) {
82+
print(`skip '${app$name}'!`);
83+
}
7884
}
79-
} else {
80-
# stop the workflow
81-
const context_err = dependency.context_env_missing(dependency$context);
82-
const file_err = dependency.workfiles_missing(dependency$file);
83-
const msg_err = [
84-
"There are some dependency of current analysis application is not satisfied:",
85-
paste(c("analysis_app:", app$name), sep = " ")
86-
];
8785

88-
throw_err([msg_err, context_err, file_err]);
86+
NULL;
8987
}
9088

91-
app$profiler = {
92-
time: time_span(now() - t0)
93-
};
94-
9589
invisible(NULL);
96-
}
90+
}

R/workflowRender.R

Lines changed: 0 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -31,93 +31,3 @@ const run = function(registry = NULL, disables = list()) {
3131

3232
__runImpl(context = .get_context(), disables);
3333
}
34-
35-
#' Internal Workflow Execution Engine
36-
#'
37-
#' @description
38-
#' An internal function that drives the execution of a modular workflow.
39-
#' It sequentially processes analysis modules according to the pipeline
40-
#' configuration while respecting disablement rules.
41-
#'
42-
#' @param context A workflow context object containing:
43-
#' \itemize{
44-
#' \item{pipeline - character vector of module execution order}
45-
#' \item{workflow - list of module definitions}
46-
#' }
47-
#' @param disables A named list specifying module disablement status.
48-
#' Format: `list(module_name = TRUE/FALSE)`. Modules with TRUE will be skipped.
49-
#'
50-
#' @details
51-
#' This function:
52-
#' \enumerate{
53-
#' \item Retrieves module execution order from `context$pipeline`
54-
#' \item Checks disablement status through two mechanisms:
55-
#' \itemize{
56-
#' \item Explicit disablement via `disables` parameter
57-
#' \item Module's own `disable` property (set by upstream modules)
58-
#' }
59-
#' \item Executes non-disabled modules using `.internal_call()`
60-
#' \item Provides verbose logging when `options(verbose=TRUE)`
61-
#' }
62-
#'
63-
#' The workflow context is modified in-place by module execution.
64-
#'
65-
#' @note
66-
#' This is an internal function not meant for direct calling by users.
67-
#' Modules can control subsequent module execution by setting their
68-
#' `disable` property.
69-
#'
70-
#' @return
71-
#' Invisibly returns NULL. Modifies the workflow context object in-place
72-
#' through module executions.
73-
#'
74-
#' @keywords internal
75-
#' @seealso \code{\link{.internal_call}} for module execution logic
76-
const __runImpl = function(context, disables = list()) {
77-
let app_pool = context$workflow;
78-
let skip = FALSE;
79-
let verbose = as.logical(getOption("verbose"));
80-
81-
if (verbose) {
82-
print("view module configs:");
83-
str(disables);
84-
}
85-
86-
# the pipeline data slot defines the workflow module
87-
# execute sequence.
88-
#
89-
# get a specific workflow analysis app module, and then
90-
# execute the module under a given workflow context
91-
for(let app_name in context$pipeline) {
92-
let app = app_pool[[app_name]];
93-
let skip = FALSE;
94-
95-
if (is.null(app$name)) {
96-
throw_err(`missing app module definition object for '${app_name}', please check of the app function has been hooked or not?`);
97-
}
98-
99-
if (app$name in disables) {
100-
if (as.logical(disables[[app$name]])) {
101-
skip = TRUE;
102-
}
103-
} else {
104-
if("disable" in app) {
105-
# current app module may be disable by other
106-
# application from the workflow upsteam
107-
skip = app$disable;
108-
}
109-
}
110-
111-
if (!skip) {
112-
.internal_call(app, context);
113-
} else {
114-
if (verbose) {
115-
print(`skip '${app$name}'!`);
116-
}
117-
}
118-
119-
NULL;
120-
}
121-
122-
invisible(NULL);
123-
}

0 commit comments

Comments
 (0)