Exemple #1
0
 def add_coverage_record_for(self, item):
     """Record this CoverageProvider's coverage for the given
     Edition/Identifier in the known Collection
     """
     return CoverageRecord.add_for(item,
                                   data_source=self.data_source,
                                   operation=self.operation,
                                   collection=self.collection)
Exemple #2
0
    def test_process_urn_isbn(self):
        # Create a new ISBN identifier.
        # Ask online providers for metadata to turn into an opds feed about this identifier.
        # Make sure a coverage record was created, and a 201 status obtained from provider.
        # Ask online provider again, and make sure we're now getting a 202 "working on it" status.
        # Ask again, this time getting a result.  Make sure know that got a result.

        isbn, ignore = Identifier.for_foreign_id(
            self._db, Identifier.ISBN, self._isbn
        )

        # The first time we look up an ISBN a CoverageRecord is created
        # representing the work to be done.
        self.controller.process_urn(isbn.urn)
        self.assert_one_message(
            isbn.urn, HTTP_CREATED, self.controller.IDENTIFIER_REGISTERED
        )
        [record] = isbn.coverage_records
        eq_(record.exception, self.controller.NO_WORK_DONE_EXCEPTION)
        eq_(record.status, CoverageRecord.TRANSIENT_FAILURE)

        # So long as the necessary coverage is not provided,
        # future lookups will not provide useful information
        self.controller.precomposed_entries = []
        self.controller.process_urn(isbn.urn)
        self.assert_one_message(
            isbn.urn, HTTP_ACCEPTED, self.controller.WORKING_TO_RESOLVE_IDENTIFIER
        )

        # Let's provide the coverage.
        metadata_sources = DataSource.metadata_sources_for(
            self._db, isbn
        )
        for source in metadata_sources:
            CoverageRecord.add_for(isbn, source)

        # Process the ISBN again, and we get an <entry> tag with the
        # information.
        self.controller.precomposed_entries = []
        self.controller.process_urn(isbn.urn)
        expect = isbn.opds_entry()
        [actual] = self.controller.precomposed_entries
        eq_(etree.tostring(expect), etree.tostring(actual))
Exemple #3
0
 def test_process_urn_exception_during_resolve_attempt(self):
     identifier = self._identifier(Identifier.GUTENBERG_ID)
     record, is_new = CoverageRecord.add_for(
         identifier, self.source, self.controller.OPERATION,
         status=CoverageRecord.PERSISTENT_FAILURE
     )
     record.exception = "foo"
     self.controller.process_urn(identifier.urn)
     self.assert_one_message(
         identifier.urn, HTTP_INTERNAL_SERVER_ERROR, "foo"
     )
 def test_process_urn_exception_during_resolve_attempt(self):
     identifier = self._identifier(Identifier.GUTENBERG_ID)
     record, is_new = CoverageRecord.add_for(
         identifier,
         self.source,
         self.controller.OPERATION,
         status=CoverageRecord.PERSISTENT_FAILURE)
     record.exception = "foo"
     self.controller.process_urn(identifier.urn)
     self.assert_one_message(identifier.urn, HTTP_INTERNAL_SERVER_ERROR,
                             "foo")
    def test_process_urn_no_presentation_ready_work(self):
        identifier = self._identifier(Identifier.GUTENBERG_ID)

        # There's a record of success, but no presentation-ready work.
        record, is_new = CoverageRecord.add_for(identifier,
                                                self.source,
                                                self.controller.OPERATION,
                                                status=CoverageRecord.SUCCESS)

        self.controller.process_urn(identifier.urn)
        self.assert_one_message(
            identifier.urn, HTTP_INTERNAL_SERVER_ERROR,
            self.controller.SUCCESS_DID_NOT_RESULT_IN_PRESENTATION_READY_WORK)
    def test_process_urn_isbn(self):
        # Create a new ISBN identifier.
        # Ask online providers for metadata to turn into an opds feed about this identifier.
        # Make sure a coverage record was created, and a 201 status obtained from provider.
        # Ask online provider again, and make sure we're now getting a 202 "working on it" status.
        # Ask again, this time getting a result.  Make sure know that got a result.

        isbn, ignore = Identifier.for_foreign_id(self._db, Identifier.ISBN,
                                                 self._isbn)

        # The first time we look up an ISBN a CoverageRecord is created
        # representing the work to be done.
        self.controller.process_urn(isbn.urn)
        self.assert_one_message(isbn.urn, HTTP_CREATED,
                                self.controller.IDENTIFIER_REGISTERED)
        [record] = isbn.coverage_records
        eq_(record.exception, self.controller.NO_WORK_DONE_EXCEPTION)
        eq_(record.status, CoverageRecord.TRANSIENT_FAILURE)

        # So long as the necessary coverage is not provided,
        # future lookups will not provide useful information
        self.controller.precomposed_entries = []
        self.controller.process_urn(isbn.urn)
        self.assert_one_message(isbn.urn, HTTP_ACCEPTED,
                                self.controller.WORKING_TO_RESOLVE_IDENTIFIER)

        # Let's provide the coverage.
        metadata_sources = DataSource.metadata_sources_for(self._db, isbn)
        for source in metadata_sources:
            CoverageRecord.add_for(isbn, source)

        # Process the ISBN again, and we get an <entry> tag with the
        # information.
        self.controller.precomposed_entries = []
        self.controller.process_urn(isbn.urn)
        expect = isbn.opds_entry()
        [actual] = self.controller.precomposed_entries
        eq_(etree.tostring(expect), etree.tostring(actual))
Exemple #7
0
    def test_process_urn_no_presentation_ready_work(self):
        identifier = self._identifier(Identifier.GUTENBERG_ID)

        # There's a record of success, but no presentation-ready work.
        record, is_new = CoverageRecord.add_for(
            identifier, self.source, self.controller.OPERATION,
            status=CoverageRecord.SUCCESS
        )

        self.controller.process_urn(identifier.urn)
        self.assert_one_message(
            identifier.urn, HTTP_INTERNAL_SERVER_ERROR,
            self.controller.SUCCESS_DID_NOT_RESULT_IN_PRESENTATION_READY_WORK
        )
Exemple #8
0
    def test_process_urn_pending_resolve_attempt(self):
        # Simulate calling process_urn twice, and make sure the 
        # second call results in an "I'm working on it, hold your horses" message.
        identifier = self._identifier(Identifier.GUTENBERG_ID)

        record, is_new = CoverageRecord.add_for(
            identifier, self.source, self.controller.OPERATION,
            status=CoverageRecord.TRANSIENT_FAILURE
        )
        record.exception = self.controller.NO_WORK_DONE_EXCEPTION

        self.controller.process_urn(identifier.urn)
        self.assert_one_message(
            identifier.urn, HTTP_ACCEPTED,
            URNLookupController.WORKING_TO_RESOLVE_IDENTIFIER
        )
    def test_process_urn_pending_resolve_attempt(self):
        # Simulate calling process_urn twice, and make sure the
        # second call results in an "I'm working on it, hold your horses" message.
        identifier = self._identifier(Identifier.GUTENBERG_ID)

        record, is_new = CoverageRecord.add_for(
            identifier,
            self.source,
            self.controller.OPERATION,
            status=CoverageRecord.TRANSIENT_FAILURE)
        record.exception = self.controller.NO_WORK_DONE_EXCEPTION

        self.controller.process_urn(identifier.urn)
        self.assert_one_message(
            identifier.urn, HTTP_ACCEPTED,
            URNLookupController.WORKING_TO_RESOLVE_IDENTIFIER)
Exemple #10
0
    def register_identifier_as_unresolved(self, urn, identifier):
        # This identifier could have a presentation-ready Work
        # associated with it, but it doesn't. We need to make sure the
        # work gets done eventually by creating a CoverageRecord
        # representing the work that needs to be done.
        source = DataSource.lookup(self._db, DataSource.INTERNAL_PROCESSING)

        record = CoverageRecord.lookup(identifier, source, self.OPERATION)
        is_new = False
        if not record:
            # There is no existing CoverageRecord for this Identifier.
            # Create one, but put it in a state of transient failure
            # to represent the fact that work needs to be done.
            record, is_new = CoverageRecord.add_for(
                identifier,
                source,
                self.OPERATION,
                status=CoverageRecord.TRANSIENT_FAILURE)
            record.exception = self.NO_WORK_DONE_EXCEPTION

        if is_new:
            # The CoverageRecord was just created. Tell the client to
            # come back later.
            return self.add_message(urn, HTTP_CREATED,
                                    self.IDENTIFIER_REGISTERED)
        else:
            # There is a pending attempt to resolve this identifier.
            # Tell the client we're working on it, or if the
            # pending attempt resulted in an exception,
            # tell the client about the exception.
            message = record.exception
            if not message or message == self.NO_WORK_DONE_EXCEPTION:
                message = self.WORKING_TO_RESOLVE_IDENTIFIER
            status = HTTP_ACCEPTED
            if record.status == record.PERSISTENT_FAILURE:
                # Apparently we just can't provide coverage of this
                # identifier.
                status = HTTP_INTERNAL_SERVER_ERROR
            elif record.status == record.SUCCESS:
                # This shouldn't happen, since success in providing
                # this sort of coverage means creating a presentation
                # ready work. Something weird is going on.
                status = HTTP_INTERNAL_SERVER_ERROR
                message = self.SUCCESS_DID_NOT_RESULT_IN_PRESENTATION_READY_WORK
            return self.add_message(urn, status, message)
Exemple #11
0
    def register_identifier_as_unresolved(self, urn, identifier):
        # This identifier could have a presentation-ready Work
        # associated with it, but it doesn't. We need to make sure the
        # work gets done eventually by creating a CoverageRecord
        # representing the work that needs to be done.
        source = DataSource.lookup(self._db, DataSource.INTERNAL_PROCESSING)
        
        record = CoverageRecord.lookup(identifier, source, self.OPERATION)
        is_new = False
        if not record:
            # There is no existing CoverageRecord for this Identifier.
            # Create one, but put it in a state of transient failure
            # to represent the fact that work needs to be done.
            record, is_new = CoverageRecord.add_for(
                identifier, source, self.OPERATION,
                status=CoverageRecord.TRANSIENT_FAILURE
            )
            record.exception = self.NO_WORK_DONE_EXCEPTION

        if is_new:
            # The CoverageRecord was just created. Tell the client to
            # come back later.
            return self.add_message(urn, HTTP_CREATED, self.IDENTIFIER_REGISTERED)
        else:
            # There is a pending attempt to resolve this identifier.
            # Tell the client we're working on it, or if the
            # pending attempt resulted in an exception,
            # tell the client about the exception.
            message = record.exception
            if not message or message == self.NO_WORK_DONE_EXCEPTION:
                message = self.WORKING_TO_RESOLVE_IDENTIFIER
            status = HTTP_ACCEPTED
            if record.status == record.PERSISTENT_FAILURE:
                # Apparently we just can't provide coverage of this
                # identifier.
                status = HTTP_INTERNAL_SERVER_ERROR
            elif record.status == record.SUCCESS:
                # This shouldn't happen, since success in providing
                # this sort of coverage means creating a presentation
                # ready work. Something weird is going on.
                status = HTTP_INTERNAL_SERVER_ERROR
                message = self.SUCCESS_DID_NOT_RESULT_IN_PRESENTATION_READY_WORK
            return self.add_message(urn, status, message)