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)
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))
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))
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_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)
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)
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)