Quamina doesn't currently
support RemPattern
. Some of the contemplated implementations of
RemPattern
are difficult. At least one approach is pretty easy:
Wrap the current matcher to filter removed patterns from match results
and periodically rebuild the matcher from scrach with the live
patterns. More specifically:
- Remember patterns that have been added
- Remember patterns that have been removed (implicitly)
- Filter
MatchedFor...()
results to remove any removed patterns - Support rebuilding the matcher state periodically with only the live patterns
- Maintain some statistics to help decide when to rebuild
The implementation of the set of live patterns is pluggable via a Go
interface. The default implementation is a map[quamina.X]string
.
Rebuilding can be triggered automatically using either an application-provided trigger function, which can be based on state statistics, or the default trigger policy, which fires when the removed/live ratio is greater than 1 (and there are at least 100 live patterns).
-
Embed the real matcher in a new type that extends the real matcher with the new method
RemPattern
. This new type will have its ownAddPattern
andMatchesFor...
methods that wrap those of the underlying methods.The new
RemPattern
andAddPattern
will also call a pluggable rebuild trigger function. If that function returns true, a rebuild is executed synchronously inside the method bodies. This behavior can result in substantial latency for that method call. As an alternative, an application can use a rebuild trigger that never returns true and instead manually callRebuild
(perhaps after consultingStats
).Since the nature of this beast is somewhat different from that of the core Quamina design, use a new package (within the Quamina repo). That way core Quamina isn't contaminated, and an application can use pure Quanima without the overhead of
RemPattern
support. -
Maintain a possibly persistent map of live patterns
quamina.X
→pattern
, which is modified byAddPattern
andRemPattern
. -
MatchesFor...
is implemented by calling the underlying matcher'sMatchesFor...
and then removing the returnedquamina.X
s that re not in the live set of patterns. -
Provide a
Rebuild
method that rebuilds the entire underlying matcher from scratch based on the live set of patterns. The application has to callRebuild
to compact the matcher state.The
Rebuild
method could remove the old matcher before it builds the new one. That technique could maybe reduce heap demands compared to keeping the old matcher around until the rebuild completes. In theory, the rebuild should never encounter a problem except for memory exhaustion, and in that case prospects are grim anyway. But if the rebuild process does run into a non-fatal problem, the matcher state would be lost. As an experiment, the currentRebuild
method takes afearlessly
boolean arguent, which, if false, does not release the previous matcher until the rebuild completes successfully. -
Maintain some basic statistics (
Added
,Removed
, andFiltered
counts) to aid callers in implementing reasonable rebuild policies.
The default state is a map[quamina.X]string
with the obivous
dimensions: an entry for every live pattern. With that
implementation, here's the pretty obvious story on time and space
overhead:
-
AddPattern
: Overhead: A hash table get and a hash table add. -
RemPattern
: No overhead in the sense that this method is what we're here for. Costs: a hash table get and a hash table rem. (We could omit the first hash table op if we don't want to report whether the pattern was actually removed.) -
MatchesFor...
: A hash table get for every returnedquamina.X
; also allocates a new array. -
Rebuild
: As discussed above, "fearless" rebuilds at least pretend to minimize demands on the heap during a rebuild. This method performs an underlyingAddPattern
for every live pattern.