Beispiel #1
0
    def test_get_available_services(self):

        # Check that all services are returned by get_available_services() when no further parameters are given
        for service in available_services:
            self.assertIn(service, get_available_services())

        # Check that using an include filter only returns included service
        self.assertIn(available_services[0].name, get_available_services(include=[available_services[0].name])[0].name)
        self.assertEquals(len(get_available_services(include=[available_services[0].name])), 1)

        # Check that using an empty list include filter returns no services
        self.assertEquals(len(get_available_services(include=[])), 0)

        # Check that using an empty list for exclude has no effect
        self.assertEquals(len(get_available_services(exclude=[])), len(get_available_services()))

        # Check that excluding a services removes it from the list
        self.assertNotIn(available_services[0], get_available_services(exclude=[available_services[0].name]))

        # Check filtering by component
        self.assertEquals(len(get_available_services(component="nonExistingComponent")), 0)
        components = list()
        for service in available_services:
            components += service.implemented_components
        component = components[0]
        count = components.count(component)
        self.assertEquals(len(get_available_services(component=component)), count)
Beispiel #2
0
def get_application_monitor_data(request, pk):
    """
    Returns API client usage data to be shown in the monitor page.
    This view should return a JSON response with a 'data' field including a list of API usage event.
    Each event should include a 'date' field with the timestamp as returned by Pythons Datetime.timestamp() object
    (https://docs.python.org/3/library/datetime.html#datetime.datetime.timestamp) and with a 'service' property
    with the service name (to which a request was forwarded).
    """
    #application = get_object_or_404(ApiClient, pk=pk)
    fake_data_points = list()
    today = datetime.datetime.today()
    services = get_available_services()
    import random
    N_FAKE_POINTS = 1000
    DAYS_SPAN = 60
    for i in range(0, N_FAKE_POINTS):
        fake_data_points.append({
            'date': (today - datetime.timedelta(minutes=random.randint(0, 60*24*DAYS_SPAN))).timestamp(),
            'service': random.choice(services).name,
        })
    return JsonResponse({'data': fake_data_points})
Beispiel #3
0
def services(request):
    """
    .. http:get:: /services/

        This endpoint returns information about all third party services available in the Audio
        Commons Ecosystem. For each service, a list of components is provided informing of what
        parts of the Audio Commons API are supported.

        Returned services can be filtered using the ``component`` query parameter.

        :query component: only return services that implement this component

        :statuscode 200: no error
        :statuscode 401: no authentication details provided

        **Response**

        Response is a dictionary like the example below.
        Note that this endpoint **does not return an aggregated response** but a direct response
        (response does not need to be collected).

        .. code:: json

            {
                "services": {
                    "Freesound": {
                        "id": "aaa099c0",
                        "components": [
                            "text_search"
                        ],
                        "description": {
                            "text_search": {
                                "supported_fields": [
                                    "ac:url",
                                    "ac:author_name",
                                    "ac:id"
                                ]
                            }
                        },
                        "url": "http://www.freesound.org"
                    },
                    "Jamendo": {
                        "id": "tya056c0",
                        "components": [
                            "licensing",
                            "text_search"
                        ],
                        "description": {
                            "text_search": {
                                "supported_fields": [
                                    "ac:url",
                                    "ac:author_name",
                                    "ac:id",
                                    "ac:license"
                                ]
                            }
                        },
                        "url": "http://www.jamendo.com"
                    }
                },
                "count": 2
            }
    """
    # TODO: implement support for JSON-LD format. Needs to call get_request_context(request)['format'] and check
    services = get_available_services(
        component=request.GET.get('component', None))
    return Response({
        'count': len(services),
        'services': {
            service.name: {
                'id': service.id,
                'url': service.url,
                'components': service.implemented_components,
                'description': service.get_service_description(),
            }
            for service in services
        }
    })
    def process_request(request,
                        wait_until_complete=False,
                        include=None,
                        exclude=None,
                        acid_domain=None):
        """
        Process incoming request, and propagate it to corresponding services.
        Requests to 3rd party services are made asynchronously. We send requests to all 3rd
        party services and as soon as a response is received it is added to a response object
        which aggregates the responses from all services.
        In the normal functioning mode (wait_until_complete=False) this method will immediately
        return a response right after all requests have been sent. This response will mainly
        include a response_id parameter that can be later used to pull the actual responses
        from the 3rd party services (see ResponseAggregator.collect_response).
        If wait_until_complete is set to False, then this method will wait untill a response is
        received for all requests and only then will return an aggregated response including the
        contents of all 3rd party services individual responses.

        :param request: incoming request object
        :param wait_until_complete: whether to return immediately after all requests are sent or wait untill all responses are received
        :param include: list of service names to include when getting available services
        :param include: list of service names to exclude when getting available services
        :param acid_domain: domain of Audio Commons Unique Identifiers to be considered for matching available services
        :return: dictionary with response (as returned by ResponseAggregator.collect_response)
        """

        # Get available services for the given component (e.g. services that do `text search')
        services = get_available_services(component=request['component'],
                                          include=include,
                                          exclude=exclude)

        # Filter by ACID domain (e.g. select only services that support the requested ACID domain)
        if acid_domain is not None:
            services = [
                service for service in services if acid_domain in
                service.get_service_description()[request['component']].get(
                    ACID_DOMAINS_DESCRIPTION_KEYWORD, list())
            ]

        if not services:
            # If no services have been found for the requested component or combination of component
            # and acid domain, we raise an exception
            raise ACAPINoServiceAvailable

        # Create object to store responses from services
        response_id = response_aggregator.create_response(len(services))
        if not services:
            # No services will be queries, response can be set to finished
            response_aggregator.set_response_to_finished(response_id)
        else:
            response_aggregator.set_response_to_processing(response_id)

        if not settings.DEBUG or settings.USE_CELERY_IN_DEBUG_MODE:
            # Iterate over services, perform requests and aggregate responses
            async_response_objects = list()
            for service in services:
                # Requests are performed asynchronously in Celery workers
                async_response_objects.append(
                    perform_request_and_aggregate.delay(
                        request, response_id, service.id))

            # Wait until all responses are received (only if wait_until_complete == True)
            if wait_until_complete:
                # We wait until we get a response for all the requests we sent
                # We do that by continuously iterating over all async_response_objetcs in a while
                # loop and only exit when all of them have been flagged as ready
                # TODO: we should add some control over timeouts, etc as this operation is blocking
                while True:
                    if all([item.ready() for item in async_response_objects]):
                        break
        else:
            # When in debug mode AND not settings.USE_CELERY_IN_DEBUG_MODE
            # wait_until_complete is ignored as web server does not do the requests asynchronously
            async_response_objects = list()
            for service in services:
                # Requests are performed synchronously in the web server
                async_response_objects.append(
                    perform_request_and_aggregate(request, response_id,
                                                  service.id))

        # Return object including responses received so far (if wait_until_complete == False the
        # response returned here will almost only contain the response_id field which can be later
        # used to retrieve further responses.
        return response_aggregator.collect_response(
            response_id, format=request['context']['format'])