cmsig/seal-multi-adapter
SEAL Multi Adapter writes indexing operations to multiple adapters at once. Commonly paired with ReadWriteAdapter to keep search reads on one engine while mirroring writes to several indexes, useful during migrations or multi-backend setups.
Install the Package:
composer require cmsig/seal-multi-adapter
Basic Usage:
Combine with ReadWriteAdapter to write to multiple adapters while reading from one:
use CmsIg\Seal\Adapter\Elasticsearch\ElasticsearchAdapter;
use CmsIg\Seal\Adapter\Multi\MultiAdapter;
use CmsIg\Seal\Adapter\ReadWrite\ReadWriteAdapter;
use CmsIg\Seal\Engine;
$readAdapter = new ElasticsearchAdapter($readConfig);
$writeAdapter1 = new ElasticsearchAdapter($writeConfig1);
$writeAdapter2 = new ElasticsearchAdapter($writeConfig2);
$multiAdapter = new MultiAdapter($readAdapter, $writeAdapter1, $writeAdapter2);
$engine = new Engine(
new ReadWriteAdapter($readAdapter, $multiAdapter),
$schema
);
First Use Case: Sync data to multiple search engines (e.g., Elasticsearch + Algolia) while querying only one.
Write Operations:
Use MultiAdapter to propagate writes to all configured adapters:
$multiAdapter->addDocument($document); // Writes to all adapters
$multiAdapter->updateDocument($id, $data); // Updates all adapters
$multiAdapter->deleteDocument($id); // Deletes from all adapters
Read Operations:
Delegate reads to a single adapter (e.g., ReadWriteAdapter):
$readWriteAdapter->search($query); // Queries only the read adapter
DSN Configuration:
Define adapters in .env for framework integration:
# Read adapter (e.g., Elasticsearch)
elastic://localhost:9200?index=products
# Multi adapter (writes to Elasticsearch + Algolia)
multi://elastic?adapters[]=algolia://localhost:9200?index=products_algolia
# ReadWrite adapter (reads from Elasticsearch, writes via MultiAdapter)
read-write://elastic?write=multi
MultiAdapter operations in transactions or retry logic for idempotency:
try {
$multiAdapter->addDocument($document);
} catch (\Exception $e) {
// Log or retry failed writes
}
No Search Support:
MultiAdapter does not support search()—always use it with ReadWriteAdapter for queries.
// ❌ Fails
$multiAdapter->search($query);
// ✅ Works
$readWriteAdapter->search($query);
Adapter Compatibility:
All adapters must implement the same methods (e.g., addDocument, updateDocument). Mismatches cause runtime errors.
DSN Parsing:
Ensure DSN strings are correctly formatted (e.g., multi://readAdapter?adapters[]=writeAdapter1&adapters[]=writeAdapter2).
$multiAdapter->addDocument($document, function ($adapter, $result) {
\Log::debug("Write to {$adapter::class}: " . json_encode($result));
});
Custom Adapters:
Extend MultiAdapter to support custom logic (e.g., conditional writes):
class ConditionalMultiAdapter extends MultiAdapter {
public function addDocument($document, $options = []) {
if ($this->shouldWrite($document)) {
parent::addDocument($document, $options);
}
}
}
Priority Adapters:
Override writeToAdapters() to control write order or failure handling:
protected function writeToAdapters($method, $args) {
foreach ($this->adapters as $adapter) {
try {
$adapter->$method(...$args);
} catch (\Exception $e) {
// Handle failure (e.g., skip or rethrow)
}
}
}
Bulk Operations: Optimize bulk writes by batching requests to each adapter:
$multiAdapter->bulkAddDocuments([$doc1, $doc2], 2); // Batch size = 2
How can I help you explore Laravel packages today?