Ejemplo n.º 1
0
def deferred_route(url_path: str) -> Response:
    status, content = 500, "Unknown error"

    # Initialize the instance ID variable outside of the try so it's available at finally
    instance_id = None

    # Prevent chaining deferred calls
    if any([token == "deferred" for token in url_path.split("/")]):
        return Response(status=400)

    try:
        # Create a new preemptible instance and wait for it to come online
        instance_opts = dict(service_account=os.getenv(ENV_SERVICE_ACCOUNT))
        instance_id = start_instance_from_image(GCE_IMAGE_ID, **instance_opts)
        instance_ip = get_internal_ip(instance_id)
        logger.log_info(
            f"Created worker instance {instance_id} with internal IP {instance_ip}"
        )

        # Wait 30 seconds before attempting to forward the request
        time.sleep(30)

        # Forward the route to the worker instance
        params = dict(request.args)
        headers = dict(request.headers)
        url_fwd = f"http://{instance_ip}/{url_path}"
        log_opts = dict(path=url_path, params=params)
        logger.log_info(f"Forwarding request to {instance_id}: {instance_ip}",
                        **log_opts)
        response = requests.get(url=url_fwd,
                                headers=headers,
                                params=params,
                                timeout=60 * 60 * 2)

        # Retrieve the response from the worker instance
        status, content = response.status_code, response.content
        logger.log_info(f"Received response from {instance_id}",
                        status=status,
                        **log_opts)

    except requests.exceptions.Timeout:
        logger.log_error(f"Request to {instance_id} timed out", path=url_path)
        status, content = 500, "Timeout"

    except Exception as exc:
        log_opts = dict(traceback=traceback.format_exc(), path=url_path)
        logger.log_error(
            f"Exception while waiting for response from {instance_id}",
            **log_opts)
        status, content = 500, "Internal exception"

    finally:
        # Shut down the worker instance now that the job is finished
        if instance_id is not None:
            delete_instance(instance_id)
            logger.log_info(f"Deleted instance {instance_id}")

    # Forward the response from the instance
    return Response(content, status=status)
Ejemplo n.º 2
0
def deferred_route(url_path: str) -> Response:
    status = 500
    content = "Unknown error"

    # Initialize the instance ID variable outside of the try so it's available at finally
    instance_id = None

    # Prevent chaining deferred calls
    if any([token == "deferred" for token in url_path.split("/")]):
        return Response(status=400)

    try:
        # Create a new preemptible instance and wait for it to come online
        instance_id = start_instance(
            service_account=os.getenv(ENV_SERVICE_ACCOUNT))
        instance_ip = get_internal_ip(instance_id)
        logger.log_info(
            f"Created worker instance {instance_id} with internal IP {instance_ip}"
        )

        # Wait 4 minutes before attempting to forward the request
        log_interval = 30
        wait_seconds = 4 * 60
        for _ in range(wait_seconds // log_interval):
            logger.log_info("Waiting for instance to start...")
            time.sleep(log_interval)

        # Forward the route to the worker instance
        url_fwd = f"http://{instance_ip}/{url_path}"
        logger.log_info(f"Forwarding request to {url_fwd}")
        params = dict(request.args)
        headers = dict(request.headers)
        response = requests.get(url=url_fwd,
                                headers=headers,
                                params=params,
                                timeout=60 * 60 * 2)

        # Retrieve the response from the worker instance
        status = response.status_code
        content = response.content
        logger.log_info(f"Received response with status code {status}")

    except:
        traceback.print_exc()
        content = "Internal exception"

    finally:
        # Shut down the worker instance now that the job is finished
        if instance_id is not None:
            delete_instance(instance_id)
            logger.log_info(f"Deleted instance {instance_id}")

    # Forward the response from the instance
    return Response(content, status=status)