Repository: rucio/rucio

Issue:
Add the possibility to reevaluate subscription when a dataset is closed
Motivation
----------
Currently subscriptions are evaluated at the creation of a DID. We might want to delay the subscription evaluation at the time the container or dataset is closed. To achieve this, we can add the possibility to set the `is_open` flag to True when a collection is closed





Discussion:

Resolving patch:
diff --git a/lib/rucio/core/did.py b/lib/rucio/core/did.py
--- a/lib/rucio/core/did.py
+++ b/lib/rucio/core/did.py
@@ -2734,6 +2734,7 @@ def set_status(scope, name, session=None, **kwargs):
     :param kwargs:  Keyword arguments of the form status_name=value.
     """
     statuses = ['open', ]
+    reevaluate_dids_at_close = config_get_bool('subscriptions', 'reevaluate_dids_at_close', raise_exception=False, default=False, session=session)
 
     update_stmt = update(
         models.DataIdentifier
@@ -2784,6 +2785,10 @@ def set_status(scope, name, session=None, **kwargs):
                     message['vo'] = scope.vo
 
                 add_message('CLOSE', message, session=session)
+                if reevaluate_dids_at_close:
+                    set_new_dids(dids=[{'scope': scope, 'name': name}],
+                                 new_flag=True,
+                                 session=session)
 
             else:
                 # Set status to open only for privileged accounts


Test patch:
diff --git a/lib/rucio/tests/test_did.py b/lib/rucio/tests/test_did.py
--- a/lib/rucio/tests/test_did.py
+++ b/lib/rucio/tests/test_did.py
@@ -29,7 +29,8 @@
 from rucio.common.utils import generate_uuid
 from rucio.core.did import (list_dids, add_did, delete_dids, get_did_atime, touch_dids, attach_dids, detach_dids,
                             get_metadata, set_metadata, get_did, get_did_access_cnt, add_did_to_followed,
-                            get_users_following_did, remove_did_from_followed, set_status)
+                            get_users_following_did, remove_did_from_followed, set_status, list_new_dids,
+                            set_new_dids)
 from rucio.core.replica import add_replica, get_replica
 from rucio.db.sqla.constants import DIDType
 from rucio.tests.common import rse_name_generator, scope_name_generator, did_name_generator
@@ -259,6 +260,25 @@ def test_circular_attach(self, root_account, rse_factory, did_factory, file_conf
         with pytest.raises(UnsupportedOperation, match='Circular attachment detected'):
             attach_dids(dids=[container1], account=root_account, **container3)
 
+    @pytest.mark.dirty
+    @pytest.mark.parametrize("file_config_mock", [
+        {"overrides": [('subscriptions', 'reevaluate_dids_at_close', 'True')]},
+    ], indirect=True)
+    def test_reevaluate_after_close(self, mock_scope, root_account, file_config_mock):
+        """ DATA IDENTIFIERS (CORE): Test that the option reevaluate_close_did set is_new to True """
+        dsn = did_name_generator('dataset')
+        add_did(scope=mock_scope, name=dsn, did_type=DIDType.DATASET, account=root_account)
+        new_dids = [did for did in list_new_dids(did_type=None, thread=None, total_threads=None, chunk_size=100000, session=None)]
+        assert {'scope': mock_scope, 'name': dsn, 'did_type': DIDType.DATASET} in new_dids
+
+        set_new_dids([{'scope': mock_scope, 'name': dsn, 'did_type': DIDType.DATASET}], None)
+        new_dids = [did for did in list_new_dids(did_type=None, thread=None, total_threads=None, chunk_size=100000, session=None)]
+        assert {'scope': mock_scope, 'name': dsn, 'did_type': DIDType.DATASET} not in new_dids
+
+        set_status(mock_scope, dsn, open=False)
+        new_dids = [did for did in list_new_dids(did_type=None, thread=None, total_threads=None, chunk_size=100000, session=None)]
+        assert {'scope': mock_scope, 'name': dsn, 'did_type': DIDType.DATASET} in new_dids
+
 
 class TestDIDApi:
 
diff --git a/lib/rucio/tests/test_judge_repairer.py b/lib/rucio/tests/test_judge_repairer.py
--- a/lib/rucio/tests/test_judge_repairer.py
+++ b/lib/rucio/tests/test_judge_repairer.py
@@ -179,7 +179,7 @@ def test_repair_a_rule_with_missing_locks(self):
         attach_dids(scope, dataset, files, self.jdoe)
 
         # Fake judge
-        re_evaluator(once=True)
+        re_evaluator(once=True, did_limit=10000)
 
         # Check if the Locks are created properly
         for file in files: