Skip to content

Commit cd9c3c3

Browse files
fix: 3342 faster touch runs and warning messages for non-existing files (#3398)
### Description This PR tries to optimize the --touch runs but running the *sleep* command only for jobs that actually need to touch files. The *sleep* command is moved into the async *touch* function and run only if there are files to be created. Sleeping inside this async should block the entire asyncio event loop, which is the desired behavior here as the order of files creation is preserved. For jobs with non-existing files, a warning messsage is displayed to the user. A new *log_warning* function is added in the Job class. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a configurable pause during file processing to enhance operational flexibility. - **Refactor** - Streamlined the process for checking and processing output files, ensuring clearer differentiation between file types. - Improved logging to notify when certain expected files are not present. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Johannes Köster <[email protected]>
1 parent 024dc32 commit cd9c3c3

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

src/snakemake/executors/touch.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from snakemake_interface_executor_plugins.executors.base import SubmittedJobInfo
1616
from snakemake_interface_executor_plugins.settings import CommonSettings
1717
from snakemake.common import async_run
18-
18+
from snakemake.logging import logger
1919
from snakemake.exceptions import print_exception
2020

2121

@@ -30,22 +30,43 @@
3030

3131

3232
class Executor(RealExecutor):
33+
SLEEPING_TIME = 0.1
34+
3335
def run_job(
3436
self,
3537
job: JobExecutorInterface,
3638
):
3739
job_info = SubmittedJobInfo(job=job)
3840
try:
39-
time.sleep(0.1)
4041

4142
if job.output:
4243

4344
async def touch():
44-
for f in job.output:
45-
if f.is_storage and await f.exists_in_storage():
45+
touch_storage_and_local_files = {
46+
f
47+
for f in job.output
48+
if f.is_storage and await f.exists_in_storage()
49+
}
50+
touch_files = {
51+
f
52+
for f in job.output
53+
if f not in touch_storage_and_local_files
54+
and await f.exists_local()
55+
}
56+
non_existing_files = (
57+
set(job.output) - touch_storage_and_local_files - touch_files
58+
)
59+
60+
if touch_files or touch_storage_and_local_files:
61+
time.sleep(Executor.SLEEPING_TIME)
62+
for f in touch_storage_and_local_files:
4663
await f.touch_storage_and_local()
47-
elif await f.exists_local():
64+
for f in touch_files:
4865
f.touch()
66+
if len(non_existing_files) > 0:
67+
logger.warning(
68+
f"Output files not touched because they don't exist: {', '.join(non_existing_files)}"
69+
)
4970

5071
async_run(touch())
5172

0 commit comments

Comments
 (0)