diff --git a/app/controllers/runtime/stagings_controller.rb b/app/controllers/runtime/stagings_controller.rb index da832c701ab..9377d41697f 100644 --- a/app/controllers/runtime/stagings_controller.rb +++ b/app/controllers/runtime/stagings_controller.rb @@ -33,7 +33,28 @@ def download_package(guid) raise ApiError.new_from_details('BlobstoreNotLocal') unless package_blobstore.local? package = PackageModel.find(guid:) - raise ApiError.new_from_details('NotFound', guid) if package.nil? + if package.nil? + # FLAKE_DEBUG: temporary instrumentation for the intermittent 404 on this + # endpoint (a just-created package un-findable by its own guid). Fires only + # on the nil path, so it is silent in normal operation. Captures, on the + # connection the SELECT actually used, whether the row is physically present + # (raw_match), how many package rows are visible at all (total_count), whether + # the surrounding transaction is still open (in_txn), and the identity of the + # db/connection/thread so a swap vs. the inserting side is detectable. + # Revert once CI has logged one occurrence. See the test-side counterpart in + # spec/unit/controllers/runtime/stagings_controller_spec.rb. + db = PackageModel.db + raw_match = db[:packages].where(guid:).count + total_count = db[:packages].count + conn_id = db.synchronize(&:object_id) + logger.error( + "FLAKE_DEBUG stagings-404 guid=#{guid} raw_match=#{raw_match} " \ + "total_count=#{total_count} in_txn=#{db.in_transaction?} " \ + "db_id=#{db.object_id} conn_id=#{conn_id} " \ + "thread_id=#{Thread.current.object_id}" + ) + raise ApiError.new_from_details('NotFound', guid) + end blob = package_blobstore.blob(guid) if blob.nil? diff --git a/spec/unit/controllers/runtime/stagings_controller_spec.rb b/spec/unit/controllers/runtime/stagings_controller_spec.rb index 3460ee5c3a3..42ba60c1d42 100644 --- a/spec/unit/controllers/runtime/stagings_controller_spec.rb +++ b/spec/unit/controllers/runtime/stagings_controller_spec.rb @@ -262,7 +262,25 @@ module VCAP::CloudController describe 'GET /staging/packages/:guid' do let(:package) { create(:package_model) } - before { authorize(staging_user, staging_password) } + # FLAKE_DEBUG: temporary instrumentation for the intermittent 404 on this + # endpoint. Force the lazy `package` INSERT here and log the db/connection/ + # thread identity of the INSERTING side, so the controller-side FLAKE_DEBUG + # line (app/controllers/runtime/stagings_controller.rb) has a baseline to + # compare against -- a connection or thread swap between insert and read is + # only conclusive with both sides logged. Revert together with the + # controller-side probe once CI has captured one occurrence. + before do + authorize(staging_user, staging_password) + + db = VCAP::CloudController::PackageModel.db + guid = package.guid + conn_id = db.synchronize(&:object_id) + warn( + "FLAKE_DEBUG stagings-404-insert guid=#{guid} " \ + "in_txn=#{db.in_transaction?} db_id=#{db.object_id} " \ + "conn_id=#{conn_id} thread_id=#{Thread.current.object_id}" + ) + end def create_test_blob tmpfile = Tempfile.new('staging-test-blob')