+ /**
+ * A batched version of BlobStore::getBlob.
+ *
+ * @param string[] $blobAddresses An array of blob addresses.
+ * @param int $queryFlags See IDBAccessObject.
+ * @throws BlobAccessException
+ * @return StatusValue A status with a map of blobAddress => binary blob data or null
+ * if fetching the blob has failed. Fetch failures errors are the
+ * warnings in the status object.
+ * @since 1.34
+ */
+ public function getBlobBatch( $blobAddresses, $queryFlags = 0 ) {
+ $errors = null;
+ $addressByCacheKey = $this->cache->makeMultiKeys(
+ $blobAddresses,
+ function ( $blobAddress ) {
+ return $this->getCacheKey( $blobAddress );
+ }
+ );
+ $blobsByCacheKey = $this->cache->getMultiWithUnionSetCallback(
+ $addressByCacheKey,
+ $this->getCacheTTL(),
+ function ( array $blobAddresses, array &$ttls, array &$setOpts ) use ( $queryFlags, &$errors ) {
+ // Ignore $setOpts; blobs are immutable and negatives are not cached
+ list( $result, $errors ) = $this->fetchBlobs( $blobAddresses, $queryFlags );
+ return $result;
+ },
+ [ 'pcGroup' => self::TEXT_CACHE_GROUP, 'pcTTL' => IExpiringStore::TTL_PROC_LONG ]
+ );
+
+ // Remap back to incoming blob addresses. The return value of the
+ // WANObjectCache::getMultiWithUnionSetCallback is keyed on the internal
+ // keys from WANObjectCache::makeMultiKeys, so we need to remap them
+ // before returning to the client.
+ $blobsByAddress = [];
+ foreach ( $blobsByCacheKey as $cacheKey => $blob ) {
+ $blobsByAddress[ $addressByCacheKey[ $cacheKey ] ] = $blob !== false ? $blob : null;
+ }
+
+ $result = StatusValue::newGood( $blobsByAddress );
+ if ( $errors ) {
+ foreach ( $errors as $error ) {
+ $result->warning( 'internalerror', $error );
+ }
+ }
+ return $result;
+ }
+