21 use Psr\Log\LoggerAwareInterface;
22 use Psr\Log\LoggerInterface;
23 use Psr\Log\NullLogger;
24 use Wikimedia\RequestTimeout\TimeoutException;
45 private $storeFactory;
54 $this->storeFactory = $factory;
55 $this->logger = $logger ?:
new NullLogger();
58 public function setLogger( LoggerInterface $logger ) {
59 $this->logger = $logger;
73 return $this->storeFactory->getStoreForUrl( $url, $params )->fetchFromURL( $url );
87 $batches = $this->storeFactory->getUrlsByProtocol( $urls );
89 foreach ( $batches as $proto => $batchedUrls ) {
90 $store = $this->storeFactory->getStore( $proto, $params );
91 $retval += $store->batchFetchFromURLs( $batchedUrls );
94 $missing = array_diff( $urls, array_keys( $retval ) );
95 foreach ( $missing as $url ) {
96 $retval[$url] =
false;
117 public function insert( $data, array $params = [], array $tryStores =
null ) {
118 $tryStores ??= $this->storeFactory->getWriteBaseUrls();
125 while ( count( $tryStores ) > 0 ) {
126 $index = mt_rand( 0, count( $tryStores ) - 1 );
127 $storeUrl = $tryStores[$index];
129 $this->logger->debug( __METHOD__ .
": trying $storeUrl" );
131 $store = $this->storeFactory->getStoreForUrl( $storeUrl, $params );
132 if ( $store ===
false ) {
136 $location = $this->storeFactory->getStoreLocationFromUrl( $storeUrl );
138 if ( $store->isReadOnly( $location ) ) {
142 $url = $store->store( $location, $data );
143 if ( strlen( $url ) ) {
148 "No URL returned by storage medium ($storeUrl)"
151 }
catch ( TimeoutException $e ) {
153 }
catch ( Exception $ex ) {
155 $msg =
'caught ' . get_class( $error ) .
' exception: ' . $error->getMessage();
158 unset( $tryStores[$index] );
159 $tryStores = array_values( $tryStores );
160 $this->logger->error(
161 "Unable to store text to external storage {store_path} ({failure})",
162 [
'store_path' => $storeUrl,
'failure' => $msg ]
170 } elseif ( $readOnlyCount ) {
177 throw new LogicException(
"Unexpected failure to store text to external store" );
187 if ( $storeUrls ===
null ) {
188 $storeUrls = $this->storeFactory->getWriteBaseUrls();
190 $storeUrls = is_array( $storeUrls ) ? $storeUrls : [ $storeUrls ];
197 foreach ( $storeUrls as $storeUrl ) {
198 $store = $this->storeFactory->getStoreForUrl( $storeUrl );
199 $location = $this->storeFactory->getStoreLocationFromUrl( $storeUrl );
200 if ( $store !==
false && !$store->isReadOnly( $location ) ) {
This is the main interface for fetching or inserting objects with ExternalStore.
insert( $data, array $params=[], array $tryStores=null)
Insert data into storage and return the assigned URL.
setLogger(LoggerInterface $logger)
fetchFromURL( $url, array $params=[])
Fetch data from given URL.
fetchFromURLs(array $urls, array $params=[])
Fetch data from multiple URLs with a minimum of round trips.
isReadOnly( $storeUrls=null)
__construct(ExternalStoreFactory $factory, LoggerInterface $logger=null)
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...