• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LibreSign / libresign / 21258207663

22 Jan 2026 05:27PM UTC coverage: 44.867%. First build
21258207663

Pull #6520

github

web-flow
Merge 08ba7eaa4 into cf0454786
Pull Request #6520: fix: prevent cache race condition workers

108 of 162 new or added lines in 8 files covered. (66.67%)

7264 of 16190 relevant lines covered (44.87%)

4.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/lib/Db/CachedQBMapper.php
1
<?php
2

3
declare(strict_types=1);
4
/**
5
 * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8

9
namespace OCA\Libresign\Db;
10

11
use OCP\AppFramework\Db\Entity;
12
use OCP\AppFramework\Db\QBMapper;
13
use OCP\ICache;
14
use OCP\ICacheFactory;
15
use OCP\IDBConnection;
16

17
/**
18
 * @template T of Entity
19
 * @template-extends QBMapper<T>
20
 */
21
abstract class CachedQBMapper extends QBMapper {
22
        protected const DEFAULT_CACHE_TTL = 30;
23

24
        private ?ICache $cache = null;
25
        private int $cacheTtl = self::DEFAULT_CACHE_TTL;
26

27
        public function __construct(
28
                IDBConnection $db,
29
                ICacheFactory $cacheFactory,
30
                string $tableName,
31
                int $cacheTtl = self::DEFAULT_CACHE_TTL,
32
        ) {
33
                parent::__construct($db, $tableName);
47✔
34
                $this->cacheTtl = $cacheTtl;
47✔
35
                if ($cacheFactory->isAvailable()) {
47✔
36
                        $this->cache = $cacheFactory->createDistributed($tableName);
47✔
37
                }
38
        }
39

40
        #[\Override]
41
        public function insert(Entity $entity): Entity {
42
                $inserted = parent::insert($entity);
15✔
43
                $this->cacheEntity($inserted);
15✔
44
                return $inserted;
15✔
45
        }
46

47
        #[\Override]
48
        public function update(Entity $entity): Entity {
49
                $updated = parent::update($entity);
13✔
50
                $this->cacheEntity($updated);
13✔
51
                return $updated;
13✔
52
        }
53

54
        #[\Override]
55
        public function delete(Entity $entity): Entity {
56
                $deleted = parent::delete($entity);
3✔
57
                $this->evictEntity($deleted);
3✔
58
                return $deleted;
3✔
59
        }
60

61
        private function cachePrefix(): string {
62
                return $this->getTableName();
21✔
63
        }
64

65
        private function cacheKey(string $key): string {
66
                return $this->cachePrefix() . ':' . $key;
21✔
67
        }
68

69
        protected function cacheGet(string $key): mixed {
70
                return $this->cache?->get($this->cacheKey($key));
19✔
71
        }
72

73
        protected function cacheSet(string $key, mixed $value): void {
74
                if ($this->cache) {
17✔
75
                        $this->cache->set($this->cacheKey($key), $value, $this->cacheTtl);
17✔
76
                }
77
        }
78

79
        protected function cacheRemove(string $key): void {
80
                if ($this->cache) {
13✔
81
                        $this->cache->remove($this->cacheKey($key));
13✔
82
                }
83
        }
84

85
        private function cacheClear(): void {
NEW
86
                if ($this->cache) {
×
NEW
87
                        $this->cache->clear($this->cachePrefix() . ':');
×
88
                }
89
        }
90

91
        /**
92
         * @return list<string>
93
         */
94
        protected function getEntityCacheKeys(Entity $entity): array {
95
                $id = $entity->getId();
17✔
96
                if ($id === null) {
17✔
NEW
97
                        return [];
×
98
                }
99
                return ['id:' . $id];
17✔
100
        }
101

102
        protected function cacheEntity(Entity $entity): void {
103
                foreach ($this->getEntityCacheKeys($entity) as $key) {
17✔
104
                        $this->cacheSet($key, $entity);
17✔
105
                }
106
        }
107

108
        private function evictEntity(Entity $entity): void {
109
                foreach ($this->getEntityCacheKeys($entity) as $key) {
3✔
110
                        $this->cacheRemove($key);
3✔
111
                }
112
        }
113
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc