🔍 Overview

These Celery tasks work together to ensure the health and safety tracked Links:

  1. check_active_links_via_google_task - checks active domains via Google Safe Browsing API, scheduled to run every 5 minutes.
  2. check_active_domains_via_dns_task - checks if active domains are resolvable (DNS check).
  3. block_link_task - blocks unsafe or unresolvable links and switches their in Voluum to a backup link.

📝 Task Definitions

@celery.task
def check_active_links_via_google_task():
    logger.info("Checking ACTIVE links via Google Safe Browsing API...")
    VoluumController.load_data()
 
    domain_map = Link.get_domains_map()
    total = len(domain_map)
    if total == 0:
        logger.info("No active domains found to check!")
        return
    # count unique domains
    logger.info(f"Found {total} active domains to check...")
 
    for chunk_domains in chunked(list(domain_map.keys())):
        logger.info(f"Checking ACTIVE domains chunk: {chunk_domains}")
        unsafe_domains = GoogleSafeBrowsing.check_links(chunk_domains)
        if unsafe_domains is None:
            continue
        for unsafe_domain, reason in unsafe_domains.items():
            for obj in domain_map[unsafe_domain]:
                logger.info(f"Active link {obj.link} is unsafe! Reason: {reason}")
                block_link_task.delay(link_id=obj.id, reason=reason)
        
        logger.info(f"Processed {len(chunk_domains)} domains, unsafe domains found: {len(unsafe_domains)}")
    logger.info("Finished checking ACTIVE links via Google Safe Browsing API.")
    check_active_domains_via_dns_task.delay()
 
 
@celery.task
def check_active_domains_via_dns_task():
    logger.info("Checking ACTIVE domains via DNS resolution...")
 
    domain_map = Link.get_domains_map()
    total = len(domain_map)
    if total == 0:
        logger.info("No active domains found to check!")
        return
    # count unique domains
    logger.info(f"Found {total} active domains to check...")
 
    count_unresolvable = 0
    for domain, objects in domain_map.items():
        if not is_domain_resolvable(domain):
            logger.warning(f"Domain {domain} is not resolvable, blocking links...")
            count_unresolvable += 1
            for obj in objects:
                logger.info(f"Blocking link {obj.link} due to domain {domain} not being resolvable.")
                block_link_task.delay(link_id=obj.id, reason=BlockReasons.DNS_NOT_RESOLVABLE.value, action_by="system")
 
    logger.info(f"Processed {total} domains, unresolvable domains found: {count_unresolvable}")
    logger.info("Finished checking ACTIVE domains via DNS resolution.")
 
 
@celery.task
def block_link_task(link_id: int, reason: str = BlockReasons.UNKNOWN.value, action_by: str = "system"):
    try:
        link = Link.objects.get(id=link_id)
    except Link.DoesNotExist:
        logger.error(f"Link with ID {link_id} does not exist!")
        return
    if link.status != LinkStatuses.ACTIVE.value:
        logger.warning(f"Link {link.link} is not active, cannot block!")
        return
    link.set_block(reason=reason, with_switch=True, action_by=action_by)
    logger.info(f"Link {link.link} blocked successfully!")

📑 Attributes

This attributes used for block_link_task:

NameTypeDescription
link_idintPrimary key of the Link to block.
reasonstrBlock reason (e.g., UNKNOWN, DNS_NOT_RESOLVABLE, Safe Browsing).
action_bystrActor causing the block (system or other identifier).

⚙️ Task Behavior & Flow

  1. Link Safety Check

    • Loads link data via VoluumController.load_data().
    • Retrieves unique domains from active links.
    • Splits active domains into chunks by 500 items.
    • Calls GoogleSafeBrowsing.check_links(...).
    • Enqueues block_link_task for each unsafe domain.
    • Runs check_active_domains_via_dns_task after processing all links.
  2. Domain Resolution Check

    • Retrieves unique domains from active links.
    • Uses is_domain_resolvable() to test DNS.
    • Enqueues block_link_task for each unresolvable domain.
  3. Blocking Operation

    • Fetches the Link model by link_id.
    • If still active, calls link.set_block() with the given reason and actor.
    • Logs success, warning, or error if the link does not exist or is inactive.