def METHOD_NAME(projects: Sequence[Project]) -> None:
    num_clustered = 0
    try:
        for project in projects:
            with sentry_sdk.start_span(op="txcluster_project") as span:
                span.set_data("project_id", project.id)
                tx_names = list(redis.get_transaction_names(project))
                new_rules = []
                if len(tx_names) >= MERGE_THRESHOLD:
                    clusterer = TreeClusterer(merge_threshold=MERGE_THRESHOLD)
                    clusterer.add_input(tx_names)
                    new_rules = clusterer.get_rules()
                track_clusterer_run(ClustererNamespace.TRANSACTIONS, project)
                # The Redis store may have more up-to-date last_seen values,
                # so we must update the stores to bring these values to
                # project options, even if there aren't any new rules.
                num_rules_added = rules.update_rules(
                    ClustererNamespace.TRANSACTIONS, project, new_rules
                )
                # Track a global counter of new rules:
                metrics.incr("txcluster.new_rules_discovered", num_rules_added)
                # Clear transaction names to prevent the set from picking up
                # noise over a long time range.
                redis.clear_samples(ClustererNamespace.TRANSACTIONS, project)
            num_clustered += 1
    finally:
        unclustered = len(projects) - num_clustered
        if unclustered > 0:
            metrics.incr(
                "txcluster.cluster_projects.unclustered", amount=unclustered, sample_rate=1.0
            )