22
22
23
23
"""
24
24
25
+ from contextlib import suppress
25
26
from enum import Enum
26
27
import errno
28
+ from collections import deque
27
29
import os
28
30
from pathlib import Path
29
31
import re
@@ -620,8 +622,29 @@ def get_workflow_srv_dir(id_):
620
622
return os .path .join (run_d , WorkflowFiles .Service .DIRNAME )
621
623
622
624
625
+ def refresh_nfs_cache (path : Path ):
626
+ """Refresh NFS cache for dirs between ~/cylc-run and <path> inclusive.
627
+
628
+ On NFS filesystems, the non-existence of files/directories may become
629
+ cashed. To work around this, we can list the contents of these directories
630
+ which refreshes the NFS cache.
631
+
632
+ See: https://github.com/cylc/cylc-flow/issues/6506
633
+
634
+ Arguments:
635
+ path: The directory to refresh.
636
+
637
+ Raises:
638
+ FileNotFoundError: If any of the directories between ~/cylc-run and
639
+ this directory (inclsive) are not present.
640
+
641
+ """
642
+ cylc_run_dir = get_cylc_run_dir ()
643
+ for subdir in reversed (path .relative_to (cylc_run_dir ).parents ):
644
+ deque ((cylc_run_dir / subdir ).iterdir (), maxlen = 0 )
645
+
646
+
623
647
def load_contact_file (id_ : str , run_dir = None ) -> Dict [str , str ]:
624
- """Load contact file. Return data as key=value dict."""
625
648
if not run_dir :
626
649
path = Path (get_contact_file_path (id_ ))
627
650
else :
@@ -630,6 +653,14 @@ def load_contact_file(id_: str, run_dir=None) -> Dict[str, str]:
630
653
WorkflowFiles .Service .DIRNAME ,
631
654
WorkflowFiles .Service .CONTACT
632
655
)
656
+
657
+ if not path .exists ():
658
+ # work around NFS caching issues
659
+ try :
660
+ refresh_nfs_cache (path )
661
+ except FileNotFoundError as exc :
662
+ raise ServiceFileError ("Couldn't load contact file" ) from exc
663
+
633
664
try :
634
665
with open (path ) as f :
635
666
file_content = f .read ()
@@ -919,6 +950,11 @@ def infer_latest_run(
919
950
except ValueError :
920
951
raise ValueError (f"{ path } is not in the cylc-run directory" ) from None
921
952
953
+ if not path .exists ():
954
+ # work around NFS caching issues
955
+ with suppress (FileNotFoundError ):
956
+ refresh_nfs_cache (path )
957
+
922
958
if not path .exists ():
923
959
raise InputError (
924
960
f'Workflow ID not found: { id_ } \n (Directory not found: { path } )'
0 commit comments