Skip to content

Commit 557045a

Browse files
committed
keep track of removed aggregates to reduce the number of operations inside a filesystem transaction
1 parent 20a6f7e commit 557045a

2 files changed

Lines changed: 57 additions & 32 deletions

File tree

src/Adapter/Filesystem/Repository.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ public function add(Aggregate $data): Attempt
9393
($this->encode)($data),
9494
);
9595

96-
return $this->transaction->mutate(
97-
static fn($adapter) => $adapter->add($encoded),
98-
);
96+
return $this->transaction->mutate($encoded);
9997
}
10098

10199
#[\Override]
@@ -105,9 +103,7 @@ public function update(Diff $data): Attempt
105103
($this->encode)($data),
106104
);
107105

108-
return $this->transaction->mutate(
109-
static fn($adapter) => $adapter->add($encoded),
110-
);
106+
return $this->transaction->mutate($encoded);
111107
}
112108

113109
#[\Override]
@@ -136,9 +132,7 @@ public function remove(Aggregate\Id $id): Attempt
136132
Name::of($id->value()),
137133
);
138134

139-
return $this->transaction->mutate(
140-
static fn($adapter) => $adapter->add($mutated),
141-
);
135+
return $this->transaction->mutate($mutated);
142136
}
143137

144138
#[\Override]

src/Adapter/Filesystem/Transaction.php

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
use Innmind\Immutable\{
1313
Attempt,
1414
Sequence,
15+
Map,
16+
Set,
1517
SideEffect,
1618
Predicate\Instance,
1719
};
@@ -22,13 +24,18 @@
2224
final class Transaction implements TransactionInterface
2325
{
2426
private Adapter $committed;
25-
/** @var Sequence<callable(Adapter): Attempt<SideEffect>> */
27+
private Adapter $notCommitted;
28+
/** @var Sequence<Directory> */
2629
private Sequence $mutations;
30+
/** @var Map<non-empty-string, Set<Name>> */
31+
private Map $removals;
2732

2833
private function __construct(Adapter $committed)
2934
{
3035
$this->committed = $committed;
36+
$this->notCommitted = Adapter::inMemory();
3137
$this->mutations = Sequence::of();
38+
$this->removals = Map::of();
3239
}
3340

3441
/**
@@ -42,7 +49,7 @@ public static function of(Adapter $committed): self
4249
#[\Override]
4350
public function start(): Attempt
4451
{
45-
$this->mutations = $this->mutations->clear();
52+
$this->reset();
4653

4754
return Attempt::result(SideEffect::identity());
4855
}
@@ -59,7 +66,7 @@ public function commit(mixed $value): Attempt
5966
{
6067
return $this
6168
->apply($this->committed)
62-
->map(fn() => $this->mutations = $this->mutations->clear())
69+
->map($this->reset(...))
6370
->map(static fn() => $value);
6471
}
6572

@@ -73,49 +80,66 @@ public function commit(mixed $value): Attempt
7380
#[\Override]
7481
public function rollback(mixed $value): Attempt
7582
{
76-
$this->mutations = $this->mutations->clear();
83+
$this->reset();
7784

7885
return Attempt::result($value);
7986
}
8087

8188
/**
82-
* @param callable(Adapter): Attempt<SideEffect> $mutate
83-
*
8489
* @return Attempt<SideEffect>
8590
*/
86-
public function mutate(callable $mutate): Attempt
91+
public function mutate(Directory $directory): Attempt
8792
{
88-
$this->mutations = ($this->mutations)($mutate);
89-
90-
return Attempt::result(SideEffect::identity);
93+
$this->mutations = ($this->mutations)($directory);
94+
/** @psalm-suppress InternalMethod */
95+
$this->removals = ($this->removals)(
96+
$directory->name()->toString(),
97+
$this
98+
->removals
99+
->get($directory->name()->toString())
100+
->match(
101+
static fn($removed) => $removed->merge($directory->removed()),
102+
static fn() => $directory->removed(),
103+
),
104+
);
105+
106+
return $this->notCommitted->add($directory);
91107
}
92108

93109
public function get(Name $directory): Directory
94110
{
95-
$committed = $this
96-
->committed
111+
$notCommitted = $this
112+
->notCommitted
97113
->get($directory)
98114
->keep(Instance::of(Directory::class))
99115
->match(
100116
static fn($directory) => $directory,
101117
static fn() => Directory::of($directory),
102118
);
103-
$notCommitted = Adapter::inMemory();
104-
$_ = $notCommitted
105-
->add($committed)
106-
->unwrap();
107-
108-
$_ = $this
109-
->apply($notCommitted)
110-
->unwrap();
111-
112-
return $notCommitted
119+
$committed = $this
120+
->committed
113121
->get($directory)
114122
->keep(Instance::of(Directory::class))
115123
->match(
116124
static fn($directory) => $directory,
117125
static fn() => Directory::of($directory),
118126
);
127+
128+
$merged = $this
129+
->removals
130+
->get($directory->toString())
131+
->match(
132+
static fn($removed) => $removed->reduce(
133+
$committed,
134+
static fn(Directory $committed, $name) => $committed->remove($name),
135+
),
136+
static fn() => $committed,
137+
);
138+
139+
return $notCommitted->all()->reduce(
140+
$merged,
141+
static fn(Directory $merged, $file) => $merged->add($file),
142+
);
119143
}
120144

121145
/**
@@ -126,6 +150,13 @@ private function apply(Adapter $adapter): Attempt
126150
return $this
127151
->mutations
128152
->sink(SideEffect::identity)
129-
->attempt(static fn($_, $mutate) => $mutate($adapter));
153+
->attempt(static fn($_, $mutation) => $adapter->add($mutation));
154+
}
155+
156+
private function reset(): void
157+
{
158+
$this->notCommitted = Adapter::inMemory();
159+
$this->mutations = $this->mutations->clear();
160+
$this->removals = $this->removals->clear();
130161
}
131162
}

0 commit comments

Comments
 (0)