Repository: huggingface/dataset-viewer

Issue:
Reduce the amount of comments after parquet conversion
See https://huggingface.co/datasets/open-source-metrics/datasets-dependents/discussions/1#6537d488b33b913282d076de

> Would it make sense to just update the original message to add the different revisions that have been converted?

> I agree that editing original might be better. Translating this same situation to GitHub, I would not be happy with a bot that pings for every single commit. For example, the doc-builder bot does not write a comment for every commit in a PR, it just does a single comment and link will work. I don't think most users will want to get a new notification for every single commit. We can also not silence notifications at a repo level, so as a user i would be inclined to silence the whole org.

Let's just create a discussion that points to the refs/convert/parquet page, and ignore if a discussion already exists.


Discussion:

Resolving patch:
diff --git a/jobs/cache_maintenance/src/cache_maintenance/discussions.py b/jobs/cache_maintenance/src/cache_maintenance/discussions.py
--- a/jobs/cache_maintenance/src/cache_maintenance/discussions.py
+++ b/jobs/cache_maintenance/src/cache_maintenance/discussions.py
@@ -8,21 +8,16 @@
 
 from huggingface_hub import HfApi
 from huggingface_hub.constants import REPO_TYPE_DATASET
-from libcommon.simple_cache import (
-    DatasetWithRevision,
-    get_datasets_with_last_updated_kind,
-)
+from libcommon.simple_cache import get_datasets_with_last_updated_kind
 
 PARQUET_CACHE_KIND = "config-parquet"
 DAYS = 1
-CLOSED_STATUS = "closed"
 
 
 class ParquetCounters(TypedDict):
     datasets: int
-    messages: int
-    dismissed_messages: int
     new_discussions: int
+    dismissed_discussions: int
     errors: int
 
 
@@ -55,35 +50,30 @@ def post_messages_on_parquet_conversion(
     bot_token: str,
     parquet_revision: str,
 ) -> ParquetCounters:
-    logging.info("Post messages in Hub discussion to notify about parquet conversion")
-    datasets_with_revision = limit_to_one_dataset_per_namespace(
+    logging.info("Create a Hub discussion to notify about parquet conversion")
+    datasets = limit_to_one_dataset_per_namespace(
         get_datasets_with_last_updated_kind(kind=PARQUET_CACHE_KIND, days=DAYS)
     )
 
-    logging.info(f"Posting messages for {len(datasets_with_revision)} datasets")
+    logging.info(f"Creating discussions for {len(datasets)} datasets")
     log_batch = 100
     counters: ParquetCounters = {
         "datasets": 0,
-        "messages": 0,
-        "dismissed_messages": 0,
         "new_discussions": 0,
+        "dismissed_discussions": 0,
         "errors": 0,
     }
 
     def get_log() -> str:
         return (
-            f"{counters['messages'] } messages posted (total:"
-            f" {len(datasets_with_revision)} datasets): {counters['new_discussions']} discussions have been opened."
-            f" {counters['dismissed_messages']} messages have been dismissed because the discussion had been closed."
-            f" {counters['errors']} errors."
+            f" {counters['new_discussions']} discussions have been opened. A total of"
+            f" {len(datasets)} datasets were selected, but {counters['dismissed_discussions']} datasets"
+            f" already had a discussion (open or closed). {counters['errors']} errors."
         )
 
     hf_api = HfApi(endpoint=hf_endpoint, token=bot_token)
 
-    for dataset_with_revision in datasets_with_revision:
-        dataset = dataset_with_revision.dataset
-        revision = dataset_with_revision.revision
-
+    for dataset in datasets:
         counters["datasets"] += 1
         try:
             bot_discussions = [
@@ -95,40 +85,24 @@ def get_log() -> str:
             ]
 
             if bot_discussions:
-                if len(bot_discussions) > 1:
-                    logging.warning(
-                        f"Found {len(bot_discussions)} discussions for {dataset} with bot {bot_associated_user_name},"
-                        " only the first one will be used."
-                    )
-                discussion = bot_discussions[0]
+                counters["dismissed_discussions"] += 1
+                continue
             else:
-                discussion = hf_api.create_discussion(
+                hf_api.create_discussion(
                     repo_id=dataset,
                     repo_type=REPO_TYPE_DATASET,
-                    title=f"Notifications from {bot_associated_user_name}",
-                    description=create_discussion_description(),
+                    title="[bot] Conversion to Parquet",
+                    description=create_discussion_description(
+                        dataset=dataset,
+                        hf_endpoint=hf_endpoint,
+                        parquet_revision=parquet_revision,
+                        bot_associated_user_name=bot_associated_user_name,
+                    ),
                     token=bot_token,
                 )
                 sleep(1)
                 # ^ see https://github.com/huggingface/moon-landing/issues/7729 (internal)
                 counters["new_discussions"] += 1
-            if discussion.status == CLOSED_STATUS:
-                counters["dismissed_messages"] += 1
-                continue
-            hf_api.comment_discussion(
-                repo_id=dataset,
-                repo_type=REPO_TYPE_DATASET,
-                discussion_num=discussion.num,
-                comment=create_parquet_comment(
-                    dataset=dataset,
-                    hf_endpoint=hf_endpoint,
-                    parquet_revision=parquet_revision,
-                    dataset_revision=revision,
-                ),
-                token=bot_token,
-            )
-
-            counters["messages"] += 1
 
         except Exception as e:
             logging.warning(f"Failed to post a message for {dataset}: {e}")
@@ -144,26 +118,9 @@ def get_log() -> str:
     return counters
 
 
-def temporary_call_to_action_for_feedback() -> str:
-    return "Please comment below if you have any questions or feedback about this new notifications channel. "
-
-
-def create_discussion_description() -> str:
-    return (
-        "The Datasets Server bot will post messages here about operations such as conversion to"
-        " Parquet. There are some advantages associated with having a version of your dataset available in the "
-        "[Parquet format](https://parquet.apache.org/). You can learn more about these in the"
-        f""" [documentation](https://huggingface.co/docs/datasets-server/parquet).
-
-_{temporary_call_to_action_for_feedback()}Close the discussion if you want to stop receiving notifications._"""
-    )
-
-
-def create_parquet_comment(
-    dataset: str, hf_endpoint: str, parquet_revision: str, dataset_revision: Optional[str]
+def create_discussion_description(
+    dataset: str, hf_endpoint: str, parquet_revision: str, bot_associated_user_name: str
 ) -> str:
-    link_dataset = f" revision {dataset_revision[:7]}" if dataset_revision else ""
-
     link_parquet = create_link(
         text=parquet_revision,
         dataset=dataset,
@@ -171,9 +128,13 @@ def create_parquet_comment(
         revision_type="tree",
         revision=parquet_revision,
     )
-    return f"""Datasets Server has converted the dataset{link_dataset} to Parquet.
+    return (
+        f"The {bot_associated_user_name} bot has created a version of this dataset in the [Parquet"
+        " format](https://parquet.apache.org/). You can learn more about the advantages associated with this format"
+        f""" in the [documentation](https://huggingface.co/docs/datasets-server/parquet).
 
-The Parquet files are published to the Hub in the {link_parquet} branch."""
+The Parquet files are published in the {link_parquet} branch."""
+    )
 
 
 def create_link(
@@ -182,7 +143,7 @@ def create_link(
     return f"[`{text}`]({hf_endpoint}/datasets/{dataset}/{revision_type}/{parse.quote(revision, safe='')})"
 
 
-def limit_to_one_dataset_per_namespace(datasets_with_revision: list[DatasetWithRevision]) -> list[DatasetWithRevision]:
+def limit_to_one_dataset_per_namespace(datasets: list[str]) -> list[str]:
     """
     Limit the number of datasets to one per namespace.
 
@@ -190,20 +151,20 @@ def limit_to_one_dataset_per_namespace(datasets_with_revision: list[DatasetWithR
     The choice is arbitrary. The filtered list has no particular order.
 
     Args:
-        datasets (list[DatasetWithRevision]): The list of datasets (with revision) to filter.
+        datasets (list[str]): The list of datasets to filter.
 
     Returns:
-        list[DatasetWithRevision]: The filtered list of datasets (with revision).
+        list[str]: The filtered list of datasets.
     """
     namespaces: set[str] = set()
-    selected_datasets_with_revision: list[DatasetWithRevision] = []
-    for dataset_with_revision in datasets_with_revision:
-        namespace = get_namespace(dataset_with_revision.dataset)
+    selected_datasets: list[str] = []
+    for dataset in datasets:
+        namespace = get_namespace(dataset)
         if (namespace is None) or (namespace in namespaces):
             continue
         namespaces.add(namespace)
-        selected_datasets_with_revision.append(dataset_with_revision)
-    return selected_datasets_with_revision
+        selected_datasets.append(dataset)
+    return selected_datasets
 
 
 def get_namespace(dataset: str) -> Optional[str]:
diff --git a/libs/libcommon/src/libcommon/simple_cache.py b/libs/libcommon/src/libcommon/simple_cache.py
--- a/libs/libcommon/src/libcommon/simple_cache.py
+++ b/libs/libcommon/src/libcommon/simple_cache.py
@@ -932,13 +932,7 @@ def fetch_names(
         return []
 
 
-@dataclass
-class DatasetWithRevision:
-    dataset: str
-    revision: str
-
-
-def get_datasets_with_last_updated_kind(kind: str, days: int) -> list[DatasetWithRevision]:
+def get_datasets_with_last_updated_kind(kind: str, days: int) -> list[str]:
     """
     Get the list of datasets for which an artifact of some kind has been updated in the last days.
 
@@ -947,21 +941,21 @@ def get_datasets_with_last_updated_kind(kind: str, days: int) -> list[DatasetWit
         days (int): The number of days to look back.
 
     Returns:
-        list[DatasetWithRevision]: The list of datasets, with the git revision of the last artifact.
+        list[str]: The list of datasets.
     """
 
     pipeline = [
         {"$match": {"kind": kind, "http_status": HTTPStatus.OK, "updated_at": {"$gt": get_datetime(days=days)}}},
         {"$sort": {"updated_at": 1}},
-        {"$group": {"_id": "$dataset", "revision": {"$last": "$dataset_git_revision"}}},
-        {"$project": {"dataset": "$_id", "_id": 0, "revision": 1}},
+        {"$group": {"_id": 0, "datasets": {"$addToSet": "$dataset"}}},
+        {"$unwind": "$datasets"},
     ]
-    return list(
-        DatasetWithRevision(dataset=response["dataset"], revision=response["revision"])
-        for response in CachedResponseDocument.objects(
+    return [
+        str(dataset["datasets"])
+        for dataset in CachedResponseDocument.objects(
             kind=kind, http_status=HTTPStatus.OK, updated_at__gt=get_datetime(days=days)
         ).aggregate(pipeline)
-    )
+    ]
 
 
 # only for the tests


Test patch:
diff --git a/jobs/cache_maintenance/tests/test_discussions.py b/jobs/cache_maintenance/tests/test_discussions.py
--- a/jobs/cache_maintenance/tests/test_discussions.py
+++ b/jobs/cache_maintenance/tests/test_discussions.py
@@ -5,7 +5,7 @@
 
 import pytest
 from huggingface_hub.community import DiscussionComment
-from libcommon.simple_cache import DatasetWithRevision, upsert_response
+from libcommon.simple_cache import upsert_response
 from libcommon.utils import get_datetime
 
 from cache_maintenance.config import JobConfig
@@ -14,7 +14,6 @@
     PARQUET_CACHE_KIND,
     create_discussion_description,
     create_link,
-    create_parquet_comment,
     limit_to_one_dataset_per_namespace,
     post_messages,
 )
@@ -27,31 +26,25 @@
     fetch_bot_discussion,
 )
 
+DEFAULT_BOT_NAME = "parquet-converter"
+
 
 @pytest.mark.parametrize(
     "datasets, valid_expected_datasets",
     [
-        (set(), [set()]),
-        ({"a/b"}, [{"a/b"}]),
-        ({"a"}, [set()]),
-        ({"a/b/c"}, [set()]),
-        ({"a/b", "a/b"}, [{"a/b"}]),
-        ({"a/b", "a/c"}, [{"a/b"}, {"a/c"}]),
-        ({"a/b", "b/b"}, [{"a/b", "b/b"}]),
-        ({"a/b", "b"}, [{"a/b"}]),
+        ([], [set()]),
+        (["a/b"], [{"a/b"}]),
+        (["a"], [set()]),
+        (["a/b/c"], [set()]),
+        (["a/b", "a/b"], [{"a/b"}]),
+        (["a/b", "a/c"], [{"a/b"}, {"a/c"}]),
+        (["a/b", "b/b"], [{"a/b", "b/b"}]),
+        (["a/b", "b"], [{"a/b"}]),
     ],
 )
-def test_limit_to_one_dataset_per_namespace(datasets: set[str], valid_expected_datasets: list[set[str]]) -> None:
+def test_limit_to_one_dataset_per_namespace(datasets: list[str], valid_expected_datasets: list[set[str]]) -> None:
     assert any(
-        {
-            d.dataset
-            for d in limit_to_one_dataset_per_namespace(
-                datasets_with_revision=[
-                    DatasetWithRevision(dataset=dataset, revision=REVISION_NAME) for dataset in datasets
-                ]
-            )
-        }
-        == expected_datasets
+        set(limit_to_one_dataset_per_namespace(datasets=datasets)) == expected_datasets
         for expected_datasets in valid_expected_datasets
     )
 
@@ -88,27 +81,23 @@ def test_post_messages_in_one_dataset(job_config: JobConfig) -> None:
             bot_token=job_config.discussions.bot_token,
             parquet_revision=job_config.discussions.parquet_revision,
         )
-        # ensure one message has been posted in a dataset discussion
+        # ensure one discussion has been created
         assert counters["parquet"] == {
             "datasets": 1,
-            "messages": 1,
             "new_discussions": 1,
+            "dismissed_discussions": 0,
             "errors": 0,
-            "dismissed_messages": 0,
         }
         first_discussion = fetch_bot_discussion(dataset=dataset.repo_id)
         assert first_discussion is not None
-        assert count_comments(first_discussion) == 2
+        assert count_comments(first_discussion) == 1
         first_comment = first_discussion.events[0]
         assert isinstance(first_comment, DiscussionComment)
-        assert first_comment.content == create_discussion_description()
-        second_comment = first_discussion.events[1]
-        assert isinstance(second_comment, DiscussionComment)
-        assert second_comment.content == create_parquet_comment(
+        assert first_comment.content == create_discussion_description(
             dataset=dataset.repo_id,
             hf_endpoint=job_config.common.hf_endpoint,
             parquet_revision=job_config.discussions.parquet_revision,
-            dataset_revision=first_revision,
+            bot_associated_user_name=job_config.discussions.bot_associated_user_name or DEFAULT_BOT_NAME,
         )
         # set a new "config-parquet" entry for the dataset
         second_revision = "9a0bd9fe2a87bbb82702ed170a53cf4e86535070"
@@ -126,26 +115,13 @@ def test_post_messages_in_one_dataset(job_config: JobConfig) -> None:
             bot_token=job_config.discussions.bot_token,
             parquet_revision=job_config.discussions.parquet_revision,
         )
-        # ensure the message have been posted in the same discussion
+        # ensure no new discussion has been created
         assert counters["parquet"] == {
             "datasets": 1,
-            "messages": 1,
             "new_discussions": 0,
+            "dismissed_discussions": 1,
             "errors": 0,
-            "dismissed_messages": 0,
         }
-        second_discussion = fetch_bot_discussion(dataset=dataset.repo_id)
-        assert second_discussion is not None
-        assert first_discussion.num == second_discussion.num
-        assert count_comments(second_discussion) == 3
-        third_comment = second_discussion.events[2]
-        assert isinstance(third_comment, DiscussionComment)
-        assert third_comment.content == create_parquet_comment(
-            dataset=dataset.repo_id,
-            hf_endpoint=job_config.common.hf_endpoint,
-            parquet_revision=job_config.discussions.parquet_revision,
-            dataset_revision=second_revision,
-        )
         # close the discussion
         close_discussion(dataset=dataset.repo_id, discussion_num=first_discussion.num)
         # call post_messages again
@@ -155,18 +131,17 @@ def test_post_messages_in_one_dataset(job_config: JobConfig) -> None:
             bot_token=job_config.discussions.bot_token,
             parquet_revision=job_config.discussions.parquet_revision,
         )
-        # ensure the message has not been posted
+        # ensure no new discussion has been created
         assert counters["parquet"] == {
             "datasets": 1,
-            "messages": 0,
             "new_discussions": 0,
+            "dismissed_discussions": 1,
             "errors": 0,
-            "dismissed_messages": 1,
         }
         third_discussion = fetch_bot_discussion(dataset=dataset.repo_id)
         assert third_discussion is not None
         assert first_discussion.num == third_discussion.num
-        assert count_comments(third_discussion) == 3
+        assert count_comments(third_discussion) == 1
 
 
 def test_post_messages_with_two_datasets_in_one_namespace(job_config: JobConfig) -> None:
@@ -195,32 +170,31 @@ def test_post_messages_with_two_datasets_in_one_namespace(job_config: JobConfig)
             bot_token=job_config.discussions.bot_token,
             parquet_revision=job_config.discussions.parquet_revision,
         )
-        # ensure one message has been posted in only one dataset discussion
+        # ensure one discussion has been created
         assert counters["parquet"] == {
             "datasets": 1,
-            "messages": 1,
             "new_discussions": 1,
+            "dismissed_discussions": 0,
             "errors": 0,
-            "dismissed_messages": 0,
         }
         discussion1 = fetch_bot_discussion(dataset=dataset1.repo_id)
         discussion2 = fetch_bot_discussion(dataset=dataset2.repo_id)
         discussion = discussion1 or discussion2
         assert discussion is not None
         assert discussion1 is None or discussion2 is None
-        assert count_comments(discussion) == 2
-        comment = discussion.events[1]
+        assert count_comments(discussion) == 1
+        comment = discussion.events[0]
         assert isinstance(comment, DiscussionComment)
-        assert comment.content == create_parquet_comment(
+        assert comment.content == create_discussion_description(
             dataset=dataset1.repo_id,
             hf_endpoint=job_config.common.hf_endpoint,
             parquet_revision=job_config.discussions.parquet_revision,
-            dataset_revision=None,
-        ) or create_parquet_comment(
+            bot_associated_user_name=job_config.discussions.bot_associated_user_name or DEFAULT_BOT_NAME,
+        ) or create_discussion_description(
             dataset=dataset2.repo_id,
             hf_endpoint=job_config.common.hf_endpoint,
             parquet_revision=job_config.discussions.parquet_revision,
-            dataset_revision=None,
+            bot_associated_user_name=job_config.discussions.bot_associated_user_name or DEFAULT_BOT_NAME,
         )
 
 
@@ -250,28 +224,27 @@ def test_post_messages_in_private_or_gated_dataset(job_config: JobConfig, gated:
             bot_token=job_config.discussions.bot_token,
             parquet_revision=job_config.discussions.parquet_revision,
         )
-        # ensure one message has been posted in a dataset discussion
+        # ensure one discussion has been created
         # YES: even if it's private. Should we forbid this?
         # Normally: the cache should not contain private datasets, but a public
         # dataset can be switched to private, and for some reason, or during some
         # time, the cache can contain private datasets.
         assert counters["parquet"] == {
             "datasets": 1,
-            "messages": 1,
             "new_discussions": 1,
+            "dismissed_discussions": 0,
             "errors": 0,
-            "dismissed_messages": 0,
         }
         first_discussion = fetch_bot_discussion(dataset=dataset.repo_id)
         assert first_discussion is not None
-        assert count_comments(first_discussion) == 2
-        comment = first_discussion.events[1]
+        assert count_comments(first_discussion) == 1
+        comment = first_discussion.events[0]
         assert isinstance(comment, DiscussionComment)
-        assert comment.content == create_parquet_comment(
+        assert comment.content == create_discussion_description(
             dataset=dataset.repo_id,
             hf_endpoint=job_config.common.hf_endpoint,
             parquet_revision=job_config.discussions.parquet_revision,
-            dataset_revision=REVISION_NAME,
+            bot_associated_user_name=job_config.discussions.bot_associated_user_name or DEFAULT_BOT_NAME,
         )
 
 
@@ -294,13 +267,12 @@ def test_post_messages_for_outdated_response(job_config: JobConfig) -> None:
             bot_token=job_config.discussions.bot_token,
             parquet_revision=job_config.discussions.parquet_revision,
         )
-        # ensure no discussion has been created, because the content was too old
+        # ensure one discussion has been created, because the content was too old
         assert counters["parquet"] == {
             "datasets": 0,
-            "messages": 0,
             "new_discussions": 0,
+            "dismissed_discussions": 0,
             "errors": 0,
-            "dismissed_messages": 0,
         }
         assert fetch_bot_discussion(dataset=dataset.repo_id) is None
         # update the content
@@ -318,22 +290,21 @@ def test_post_messages_for_outdated_response(job_config: JobConfig) -> None:
             bot_token=job_config.discussions.bot_token,
             parquet_revision=job_config.discussions.parquet_revision,
         )
-        # ensure one message has been posted in a dataset discussion
+        # ensure one discussion has been created
         assert counters["parquet"] == {
             "datasets": 1,
-            "messages": 1,
             "new_discussions": 1,
+            "dismissed_discussions": 0,
             "errors": 0,
-            "dismissed_messages": 0,
         }
         first_discussion = fetch_bot_discussion(dataset=dataset.repo_id)
         assert first_discussion is not None
-        assert count_comments(first_discussion) == 2
-        comment = first_discussion.events[1]
+        assert count_comments(first_discussion) == 1
+        comment = first_discussion.events[0]
         assert isinstance(comment, DiscussionComment)
-        assert comment.content == create_parquet_comment(
+        assert comment.content == create_discussion_description(
             dataset=dataset.repo_id,
             hf_endpoint=job_config.common.hf_endpoint,
             parquet_revision=job_config.discussions.parquet_revision,
-            dataset_revision=REVISION_NAME,
+            bot_associated_user_name=job_config.discussions.bot_associated_user_name or DEFAULT_BOT_NAME,
         )
diff --git a/libs/libcommon/tests/test_simple_cache.py b/libs/libcommon/tests/test_simple_cache.py
--- a/libs/libcommon/tests/test_simple_cache.py
+++ b/libs/libcommon/tests/test_simple_cache.py
@@ -19,7 +19,6 @@
     CacheReportsPage,
     CacheReportsWithContentPage,
     CacheTotalMetricDocument,
-    DatasetWithRevision,
     InvalidCursor,
     InvalidLimit,
     delete_dataset_responses,
@@ -1081,35 +1080,31 @@ class Entry(TypedDict):
     "updated_at": BEFORE,
     "dataset_git_revision": REVISION_A,
 }
-
-DATASET_REV_A = DatasetWithRevision(dataset=DATASET_NAME, revision=REVISION_A)
-DATASET_REV_B = DatasetWithRevision(dataset=DATASET_NAME, revision=REVISION_B)
-
-
-def get_dataset(dataset_with_revision: DatasetWithRevision) -> str:
-    return dataset_with_revision.dataset
-
-
-def assert_lists_are_equal(a: list[DatasetWithRevision], b: list[DatasetWithRevision]) -> None:
-    assert sorted(a, key=get_dataset) == sorted(b, key=get_dataset)
+ENTRY_7: Entry = {
+    "kind": CACHE_KIND_A,
+    "dataset": DATASET_NAME_A,
+    "config": CONFIG_NAME_1,
+    "http_status": HTTPStatus.OK,
+    "updated_at": AFTER_1,
+    "dataset_git_revision": REVISION_A,
+}
 
 
 @pytest.mark.parametrize(
     "entries,expected_datasets",
     [
         ([], []),
-        ([ENTRY_1], [DATASET_REV_A]),
+        ([ENTRY_1], [DATASET_NAME]),
         ([ENTRY_2], []),
-        ([ENTRY_4], [DATASET_REV_B]),
+        ([ENTRY_4], [DATASET_NAME]),
         ([ENTRY_5], []),
         ([ENTRY_6], []),
-        ([ENTRY_1, ENTRY_4], [DATASET_REV_B]),
-        ([ENTRY_1, ENTRY_2, ENTRY_4, ENTRY_5, ENTRY_6], [DATASET_REV_B]),
+        ([ENTRY_1, ENTRY_4], [DATASET_NAME]),
+        ([ENTRY_1, ENTRY_2, ENTRY_4, ENTRY_5, ENTRY_6], [DATASET_NAME]),
+        ([ENTRY_1, ENTRY_7], [DATASET_NAME, DATASET_NAME_A]),
     ],
 )
-def test_get_datasets_with_last_updated_kind(
-    entries: list[Entry], expected_datasets: list[DatasetWithRevision]
-) -> None:
+def test_get_datasets_with_last_updated_kind(entries: list[Entry], expected_datasets: list[str]) -> None:
     for entry in entries:
         upsert_response(
             kind=entry["kind"],
@@ -1123,5 +1118,5 @@ def test_get_datasets_with_last_updated_kind(
         )
     kind = CACHE_KIND_A
     days = DAYS
-    assert_lists_are_equal(get_datasets_with_last_updated_kind(kind=kind, days=days), expected_datasets)
+    assert sorted(get_datasets_with_last_updated_kind(kind=kind, days=days)) == sorted(expected_datasets)
     # ^ the order is not meaningful, so we sort to make the test deterministic