40 private $loadBalancer;
46 private $wanObjectCache;
52 private $byTitleCache;
59 public function __construct(
64 $this->loadBalancer = $loadBalancer;
65 $this->localCache = $localCache;
75 $ltId = (int)$row->lt_id;
77 throw new InvalidArgumentException(
78 "LinkTarget ID is 0 for {$row->lt_title} (ns: {$row->lt_namespace})"
82 $titlevalue =
new TitleValue( (
int)$row->lt_namespace, $row->lt_title );
83 $this->addToClassCache( $ltId, $titlevalue );
94 if ( !$linkTargetId ) {
98 if ( isset( $this->byIdCache[$linkTargetId] ) ) {
99 return $this->byIdCache[$linkTargetId];
102 $value = $this->loadBalancer->getConnectionRef(
DB_REPLICA )->newSelectQueryBuilder()
103 ->caller( __METHOD__ )
104 ->table(
'linktarget' )
105 ->conds( [
'lt_id' => $linkTargetId ] )
106 ->fields( [
'lt_id',
'lt_namespace',
'lt_title' ] )
113 $linkTarget = $this->newLinkTargetFromRow( $value );
114 $this->addToClassCache( $linkTargetId, $linkTarget );
126 $existingLinktargetId = $this->getLinkTargetIdFromCache( $linkTarget );
127 if ( $existingLinktargetId ) {
128 return $existingLinktargetId;
148 $existingLinktargetId = $this->getLinkTargetIdFromCache( $linkTarget );
149 if ( $existingLinktargetId ) {
150 return $existingLinktargetId;
155 $linkTargetId = $this->fetchIdFromDbPrimary( $linkTarget, [] );
156 if ( $linkTargetId ) {
157 $this->addToClassCache( $linkTargetId, $linkTarget );
158 return $linkTargetId;
167 'lt_namespace' => $ns,
178 $linkTargetId = $this->fetchIdFromDbPrimary(
180 [
'LOCK IN SHARE MODE' ]
182 if ( !$linkTargetId ) {
183 throw new RuntimeException(
184 "Failed to create link target ID for " .
185 "lt_namespace={$ns} lt_title=\"{$title}\""
189 $this->addToClassCache( $linkTargetId, $linkTarget );
191 return $linkTargetId;
201 private function fetchIdFromDbPrimary(
202 LinkTarget $linkTarget,
203 array $queryOptions = []
205 $row = $this->loadBalancer->getConnectionRef(
DB_PRIMARY )->selectRow(
207 [
'lt_id',
'lt_namespace',
'lt_title' ],
209 'lt_namespace' => $linkTarget->getNamespace(),
210 'lt_title' => $linkTarget->getDBkey()
216 if ( !$row || !$row->lt_id ) {
219 $this->addToClassCache( (
int)$row->lt_id, $linkTarget );
221 return (
int)$row->lt_id;
224 private function addToClassCache(
int $id, LinkTarget $linkTarget ) {
225 $this->byIdCache[$id] = $linkTarget;
226 $this->byTitleCache[(string)$linkTarget] = $id;
233 $this->byIdCache = [];
234 $this->byTitleCache = [];
237 private function getLinkTargetIdFromCache(
LinkTarget $linkTarget ) {
238 $linkTargetString = (string)$linkTarget;
239 if ( isset( $this->byTitleCache[$linkTargetString] ) ) {
240 return $this->byTitleCache[$linkTargetString];
243 $res = $this->localCache->getWithSetCallback(
244 $this->localCache->makeKey(
245 'linktargetstore-id',
248 $this->localCache::TTL_HOUR,
249 function () use ( $linkTarget, $fname ) {
250 return $this->wanObjectCache->getWithSetCallback(
251 $this->wanObjectCache->makeKey(
252 'linktargetstore-id',
255 WANObjectCache::TTL_DAY,
256 function () use ( $linkTarget, $fname ) {
257 $row = $this->loadBalancer->getConnectionRef(
DB_REPLICA )->selectRow(
259 [
'lt_id',
'lt_namespace',
'lt_title' ],
261 'lt_namespace' => $linkTarget->getNamespace(),
262 'lt_title' => $linkTarget->getDBkey()
267 if ( !$row || !$row->lt_id ) {
272 return (
int)$row->lt_id;
279 $this->addToClassCache(
$res, $linkTarget );