mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-04-26 00:46:22 +02:00
Feat: TrustGraph i18n & Documentation Translation Updates (#781)
Native CLI i18n: The TrustGraph CLI has built-in translation support that dynamically loads language strings. You can test and use different languages by simply passing the --lang flag (e.g., --lang es for Spanish, --lang ru for Russian) or by configuring your environment's LANG variable. Automated Docs Translations: This PR introduces autonomously translated Markdown documentation into several target languages, including Spanish, Swahili, Portuguese, Turkish, Hindi, Hebrew, Arabic, Simplified Chinese, and Russian.
This commit is contained in:
parent
19f73e4cdc
commit
f95fd4f052
560 changed files with 236300 additions and 99 deletions
780
docs/tech-specs/multi-tenant-support.hi.md
Normal file
780
docs/tech-specs/multi-tenant-support.hi.md
Normal file
|
|
@ -0,0 +1,780 @@
|
|||
---
|
||||
layout: default
|
||||
title: "तकनीकी विनिर्देश: मल्टी-टेनेंट समर्थन"
|
||||
parent: "Hindi (Beta)"
|
||||
---
|
||||
|
||||
# तकनीकी विनिर्देश: मल्टी-टेनेंट समर्थन
|
||||
|
||||
> **Beta Translation:** This document was translated via Machine Learning and as such may not be 100% accurate. All non-English languages are currently classified as Beta.
|
||||
|
||||
## अवलोकन
|
||||
|
||||
पैरामीटर नाम विसंगतियों को ठीक करके मल्टी-टेनेंट परिनियोजन सक्षम करें जो कतार अनुकूलन को रोकते हैं, और कैसेंड्रा कीस्पेस पैरामीटराइज़ेशन जोड़ें।
|
||||
|
||||
## आर्किटेक्चर संदर्भ
|
||||
|
||||
### फ्लो-आधारित कतार समाधान
|
||||
|
||||
ट्रस्टग्राफ सिस्टम गतिशील कतार समाधान के लिए एक **फ्लो-आधारित आर्किटेक्चर** का उपयोग करता है, जो स्वाभाविक रूप से मल्टी-टेनेंसी का समर्थन करता है:
|
||||
|
||||
**फ्लो परिभाषाएँ** कैसेंड्रा में संग्रहीत हैं और इंटरफ़ेस परिभाषाओं के माध्यम से कतार नामों को निर्दिष्ट करती हैं।
|
||||
**कतार नाम टेम्प्लेट का उपयोग करते हैं** जिसमें `{id}` चर होते हैं जिन्हें फ्लो इंस्टेंस आईडी के साथ प्रतिस्थापित किया जाता है।
|
||||
**सेवाएँ गतिशील रूप से कतारों को हल करती हैं** अनुरोध समय पर फ्लो कॉन्फ़िगरेशन की खोज करके।
|
||||
**प्रत्येक किरायेदार के पास अलग-अलग कतार नामों के साथ अद्वितीय फ्लो हो सकते हैं**, जो अलगाव प्रदान करते हैं।
|
||||
|
||||
फ्लो इंटरफ़ेस परिभाषा का उदाहरण:
|
||||
```json
|
||||
{
|
||||
"interfaces": {
|
||||
"triples-store": "persistent://tg/flow/triples-store:{id}",
|
||||
"graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
जब किरायेदार ए प्रवाह `tenant-a-prod` शुरू करता है और किरायेदार बी प्रवाह `tenant-b-prod` शुरू करता है, तो उन्हें स्वचालित रूप से अलग-अलग कतारें मिलती हैं:
|
||||
`persistent://tg/flow/triples-store:tenant-a-prod`
|
||||
`persistent://tg/flow/triples-store:tenant-b-prod`
|
||||
|
||||
**मल्टी-टेनेंसी के लिए सही ढंग से डिज़ाइन की गई सेवाएं:**
|
||||
✅ **नॉलेज मैनेजमेंट (कोर)** - अनुरोधों में पारित प्रवाह कॉन्फ़िगरेशन से कतारों को गतिशील रूप से हल करता है
|
||||
|
||||
**जिन सेवाओं को ठीक करने की आवश्यकता है:**
|
||||
🔴 **कॉन्फ़िग सर्विस** - पैरामीटर नाम बेमेल होने से कतार अनुकूलन में बाधा आती है
|
||||
🔴 **लाइब्रेरियन सर्विस** - हार्डकोडेड स्टोरेज मैनेजमेंट टॉपिक (नीचे चर्चा की गई है)
|
||||
🔴 **सभी सेवाएं** - कैसेंड्रा कीस्पेस को अनुकूलित नहीं किया जा सकता है
|
||||
|
||||
## समस्या विवरण
|
||||
|
||||
### मुद्दा #1: एसिंक्रोनसप्रोसेसर में पैरामीटर नाम बेमेल
|
||||
**CLI द्वारा परिभाषित:** `--config-queue` (अस्पष्ट नामकरण)
|
||||
**Argparse द्वारा रूपांतरण:** `config_queue` (पैरामीटर डिक्ट में)
|
||||
**कोड द्वारा खोजा गया:** `config_push_queue`
|
||||
**परिणाम:** पैरामीटर को अनदेखा किया जाता है, डिफ़ॉल्ट रूप से `persistent://tg/config/config`
|
||||
**प्रभाव:** 32 से अधिक सेवाओं पर प्रभाव पड़ता है जो AsyncProcessor से विरासत में मिली हैं
|
||||
**बाधा:** मल्टी-टेनेंट डिप्लॉयमेंट किरायेदार-विशिष्ट कॉन्फ़िग कतारों का उपयोग नहीं कर सकते हैं
|
||||
**समाधान:** स्पष्टता के लिए CLI पैरामीटर का नाम बदलकर `--config-push-queue` करें (ब्रेकिंग चेंज स्वीकार्य है क्योंकि सुविधा वर्तमान में टूटी हुई है)
|
||||
|
||||
### मुद्दा #2: कॉन्फ़िग सर्विस में पैरामीटर नाम बेमेल
|
||||
**CLI द्वारा परिभाषित:** `--push-queue` (अस्पष्ट नामकरण)
|
||||
**Argparse द्वारा रूपांतरण:** `push_queue` (पैरामीटर डिक्ट में)
|
||||
**कोड द्वारा खोजा गया:** `config_push_queue`
|
||||
**परिणाम:** पैरामीटर को अनदेखा किया जाता है
|
||||
**प्रभाव:** कॉन्फ़िग सर्विस कस्टम पुश कतार का उपयोग नहीं कर सकती है
|
||||
**समाधान:** स्थिरता और स्पष्टता के लिए CLI पैरामीटर का नाम बदलकर `--config-push-queue` करें (ब्रेकिंग चेंज स्वीकार्य है)
|
||||
|
||||
### मुद्दा #3: हार्डकोडेड कैसेंड्रा कीस्पेस
|
||||
**वर्तमान:** विभिन्न सेवाओं में कीस्पेस को हार्डकोडेड के रूप में `"config"`, `"knowledge"`, `"librarian"` के रूप में परिभाषित किया गया है
|
||||
**परिणाम:** मल्टी-टेनेंट डिप्लॉयमेंट के लिए कीस्पेस को अनुकूलित नहीं किया जा सकता है
|
||||
**प्रभाव:** कॉन्फ़िग, कोर और लाइब्रेरियन सेवाएं
|
||||
**बाधा:** कई किरायेदार अलग-अलग कैसेंड्रा कीस्पेस का उपयोग नहीं कर सकते हैं
|
||||
|
||||
### मुद्दा #4: कलेक्शन मैनेजमेंट आर्किटेक्चर ✅ पूर्ण
|
||||
**पिछला:** कलेक्शन को लाइब्रेरियन कीस्पेस में एक अलग कलेक्शन टेबल के माध्यम से संग्रहीत किया जाता था
|
||||
**पिछला:** लाइब्रेरियन ने कलेक्शन बनाने/हटाने के लिए 4 हार्डकोडेड स्टोरेज मैनेजमेंट टॉपिक का उपयोग किया:
|
||||
`vector_storage_management_topic`
|
||||
`object_storage_management_topic`
|
||||
`triples_storage_management_topic`
|
||||
`storage_management_response_topic`
|
||||
**समस्याएं (हल की गई):**
|
||||
हार्डकोडेड टॉपिक को मल्टी-टेनेंट डिप्लॉयमेंट के लिए अनुकूलित नहीं किया जा सकता था
|
||||
लाइब्रेरियन और 4+ स्टोरेज सेवाओं के बीच जटिल एसिंक्रोनस समन्वय
|
||||
अलग कैसेंड्रा टेबल और प्रबंधन अवसंरचना
|
||||
महत्वपूर्ण कार्यों के लिए गैर-स्थायी अनुरोध/प्रतिक्रिया कतारें
|
||||
**कार्यान्वित समाधान:** कलेक्शन को कॉन्फ़िग सर्विस स्टोरेज में माइग्रेट किया गया, वितरण के लिए कॉन्फ़िग पुश का उपयोग किया गया
|
||||
**स्थिति:** सभी स्टोरेज बैकएंड को `CollectionConfigHandler` पैटर्न में माइग्रेट किया गया है
|
||||
|
||||
## समाधान
|
||||
|
||||
यह विनिर्देश मुद्दों #1, #2, #3 और #4 को संबोधित करता है।
|
||||
|
||||
### भाग 1: पैरामीटर नाम बेमेल को ठीक करें
|
||||
|
||||
#### परिवर्तन 1: AsyncProcessor बेस क्लास - CLI पैरामीटर का नाम बदलें
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/base/async_processor.py`
|
||||
**पंक्ति:** 260-264
|
||||
|
||||
**वर्तमान:**
|
||||
```python
|
||||
parser.add_argument(
|
||||
'--config-queue',
|
||||
default=default_config_queue,
|
||||
help=f'Config push queue {default_config_queue}',
|
||||
)
|
||||
```
|
||||
|
||||
**निश्चित:**
|
||||
```python
|
||||
parser.add_argument(
|
||||
'--config-push-queue',
|
||||
default=default_config_queue,
|
||||
help=f'Config push queue (default: {default_config_queue})',
|
||||
)
|
||||
```
|
||||
|
||||
**तर्क:**
|
||||
अधिक स्पष्ट और विस्तृत नामकरण
|
||||
आंतरिक चर नाम से मेल खाता है `config_push_queue`
|
||||
परिवर्तन स्वीकार्य है क्योंकि सुविधा वर्तमान में गैर-कार्यात्मक है
|
||||
params.get() में कोई कोड परिवर्तन आवश्यक नहीं है - यह पहले से ही सही नाम की तलाश करता है
|
||||
|
||||
#### परिवर्तन 2: कॉन्फ़िगरेशन सेवा - CLI पैरामीटर का नाम बदलें
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/config/service/service.py`
|
||||
**पंक्ति:** 276-279
|
||||
|
||||
**वर्तमान:**
|
||||
```python
|
||||
parser.add_argument(
|
||||
'--push-queue',
|
||||
default=default_config_push_queue,
|
||||
help=f'Config push queue (default: {default_config_push_queue})'
|
||||
)
|
||||
```
|
||||
|
||||
**निश्चित:**
|
||||
```python
|
||||
parser.add_argument(
|
||||
'--config-push-queue',
|
||||
default=default_config_push_queue,
|
||||
help=f'Config push queue (default: {default_config_push_queue})'
|
||||
)
|
||||
```
|
||||
|
||||
**तर्क:**
|
||||
अधिक स्पष्ट नामकरण - "config-push-queue" केवल "push-queue" से अधिक स्पष्ट है।
|
||||
आंतरिक चर नाम `config_push_queue` से मेल खाता है।
|
||||
AsyncProcessor के `--config-push-queue` पैरामीटर के साथ संगत।
|
||||
परिवर्तन स्वीकार्य है क्योंकि सुविधा वर्तमान में गैर-कार्यात्मक है।
|
||||
params.get() में कोई कोड परिवर्तन आवश्यक नहीं है - यह पहले से ही सही नाम की तलाश करता है।
|
||||
|
||||
### भाग 2: कैसेंड्रा कीस्पेस पैरामीटराइज़ेशन जोड़ें
|
||||
|
||||
#### परिवर्तन 3: cassandra_config मॉड्यूल में कीस्पेस पैरामीटर जोड़ें
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/base/cassandra_config.py`
|
||||
|
||||
**CLI तर्क जोड़ें** (`add_cassandra_args()` फ़ंक्शन में):
|
||||
```python
|
||||
parser.add_argument(
|
||||
'--cassandra-keyspace',
|
||||
default=None,
|
||||
help='Cassandra keyspace (default: service-specific)'
|
||||
)
|
||||
```
|
||||
|
||||
**पर्यावरण चर समर्थन जोड़ें** (फ़ंक्शन `resolve_cassandra_config()` में):
|
||||
```python
|
||||
keyspace = params.get(
|
||||
"cassandra_keyspace",
|
||||
os.environ.get("CASSANDRA_KEYSPACE")
|
||||
)
|
||||
```
|
||||
|
||||
**`resolve_cassandra_config()` का रिटर्न वैल्यू अपडेट करें:**
|
||||
वर्तमान में रिटर्न करता है: `(hosts, username, password)`
|
||||
बदलने पर रिटर्न करेगा: `(hosts, username, password, keyspace)`
|
||||
|
||||
**तर्क:**
|
||||
मौजूदा कैसेंड्रा कॉन्फ़िगरेशन पैटर्न के अनुरूप
|
||||
`add_cassandra_args()` के माध्यम से सभी सेवाओं के लिए उपलब्ध
|
||||
CLI और पर्यावरण चर कॉन्फ़िगरेशन दोनों का समर्थन करता है
|
||||
|
||||
#### परिवर्तन 4: कॉन्फ़िगरेशन सर्विस - पैरामीटराइज़्ड कीस्पेस का उपयोग करें
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/config/service/service.py`
|
||||
|
||||
**पंक्ति 30** - हार्डकोडेड कीस्पेस हटाएं:
|
||||
```python
|
||||
# DELETE THIS LINE:
|
||||
keyspace = "config"
|
||||
```
|
||||
|
||||
**पंक्तियाँ 69-73** - कैसेंड्रा कॉन्फ़िगरेशन रिज़ॉल्यूशन को अपडेट करें:
|
||||
|
||||
**वर्तमान:**
|
||||
```python
|
||||
cassandra_host, cassandra_username, cassandra_password = \
|
||||
resolve_cassandra_config(params)
|
||||
```
|
||||
|
||||
**निश्चित:**
|
||||
```python
|
||||
cassandra_host, cassandra_username, cassandra_password, keyspace = \
|
||||
resolve_cassandra_config(params, default_keyspace="config")
|
||||
```
|
||||
|
||||
**तर्क:**
|
||||
"config" को डिफ़ॉल्ट के रूप में रखते हुए पिछली अनुकूलता बनाए रखता है।
|
||||
`--cassandra-keyspace` या `CASSANDRA_KEYSPACE` के माध्यम से ओवरराइड करने की अनुमति देता है।
|
||||
|
||||
#### परिवर्तन 5: कोर/नॉलेज सर्विस - पैरामीटराइज़्ड कीस्पेस का उपयोग करें।
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/cores/service.py`
|
||||
|
||||
**पंक्ति 37** - हार्डकोडेड कीस्पेस को हटाएँ:
|
||||
```python
|
||||
# DELETE THIS LINE:
|
||||
keyspace = "knowledge"
|
||||
```
|
||||
|
||||
**कैसेंड्रा कॉन्फ़िगरेशन रिज़ॉल्यूशन को अपडेट करें** (कॉन्फ़िगरेशन सेवा के समान स्थान पर):
|
||||
```python
|
||||
cassandra_host, cassandra_username, cassandra_password, keyspace = \
|
||||
resolve_cassandra_config(params, default_keyspace="knowledge")
|
||||
```
|
||||
|
||||
#### परिवर्तन 6: लाइब्रेरियन सेवा - पैरामीटराइज़्ड कीस्पेस का उपयोग करें
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/librarian/service.py`
|
||||
|
||||
**पंक्ति 51** - हार्डकोडेड कीस्पेस हटाएं:
|
||||
```python
|
||||
# DELETE THIS LINE:
|
||||
keyspace = "librarian"
|
||||
```
|
||||
|
||||
**कैसेंड्रा कॉन्फ़िगरेशन रिज़ॉल्यूशन को अपडेट करें** (कॉन्फ़िगरेशन सेवा के समान स्थान पर):
|
||||
```python
|
||||
cassandra_host, cassandra_username, cassandra_password, keyspace = \
|
||||
resolve_cassandra_config(params, default_keyspace="librarian")
|
||||
```
|
||||
|
||||
### भाग 3: संग्रह प्रबंधन को कॉन्फ़िगरेशन सेवा में स्थानांतरित करें
|
||||
|
||||
#### अवलोकन
|
||||
संग्रहों को कैसेंड्रा लाइब्रेरियन कीस्पेस से कॉन्फ़िगरेशन सेवा भंडारण में स्थानांतरित करें। यह हार्ड-कोडेड भंडारण प्रबंधन विषयों को समाप्त करता है और मौजूदा कॉन्फ़िगरेशन पुश तंत्र का उपयोग करके वितरण के लिए वास्तुकला को सरल बनाता है।
|
||||
|
||||
#### वर्तमान वास्तुकला
|
||||
```
|
||||
API Request → Gateway → Librarian Service
|
||||
↓
|
||||
CollectionManager
|
||||
↓
|
||||
Cassandra Collections Table (librarian keyspace)
|
||||
↓
|
||||
Broadcast to 4 Storage Management Topics (hardcoded)
|
||||
↓
|
||||
Wait for 4+ Storage Service Responses
|
||||
↓
|
||||
Response to Gateway
|
||||
```
|
||||
|
||||
#### नई वास्तुकला
|
||||
```
|
||||
API Request → Gateway → Librarian Service
|
||||
↓
|
||||
CollectionManager
|
||||
↓
|
||||
Config Service API (put/delete/getvalues)
|
||||
↓
|
||||
Cassandra Config Table (class='collections', key='user:collection')
|
||||
↓
|
||||
Config Push (to all subscribers on config-push-queue)
|
||||
↓
|
||||
All Storage Services receive config update independently
|
||||
```
|
||||
|
||||
#### परिवर्तन 7: संग्रह प्रबंधक - कॉन्फ़िगरेशन सेवा एपीआई का उपयोग करें
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/librarian/collection_manager.py`
|
||||
|
||||
**हटाएं:**
|
||||
`LibraryTableStore` का उपयोग (पंक्तियाँ 33, 40-41)
|
||||
स्टोरेज प्रबंधन उत्पादकों का आरंभीकरण (पंक्तियाँ 86-140)
|
||||
`on_storage_response` विधि (पंक्तियाँ 400-430)
|
||||
`pending_deletions` ट्रैकिंग (पंक्तियाँ 57, 90-96, और पूरे में उपयोग)
|
||||
|
||||
**जोड़ें:**
|
||||
एपीआई कॉल के लिए कॉन्फ़िगरेशन सेवा क्लाइंट (अनुरोध/प्रतिक्रिया पैटर्न)
|
||||
|
||||
**कॉन्फ़िगरेशन क्लाइंट सेटअप:**
|
||||
```python
|
||||
# In __init__, add config request/response producers/consumers
|
||||
from trustgraph.schema.services.config import ConfigRequest, ConfigResponse
|
||||
|
||||
# Producer for config requests
|
||||
self.config_request_producer = Producer(
|
||||
client=pulsar_client,
|
||||
topic=config_request_queue,
|
||||
schema=ConfigRequest,
|
||||
)
|
||||
|
||||
# Consumer for config responses (with correlation ID)
|
||||
self.config_response_consumer = Consumer(
|
||||
taskgroup=taskgroup,
|
||||
client=pulsar_client,
|
||||
flow=None,
|
||||
topic=config_response_queue,
|
||||
subscriber=f"{id}-config",
|
||||
schema=ConfigResponse,
|
||||
handler=self.on_config_response,
|
||||
)
|
||||
|
||||
# Tracking for pending config requests
|
||||
self.pending_config_requests = {} # request_id -> asyncio.Event
|
||||
```
|
||||
|
||||
**`list_collections` को संशोधित करें (पंक्तियाँ 145-180):**
|
||||
```python
|
||||
async def list_collections(self, user, tag_filter=None, limit=None):
|
||||
"""List collections from config service"""
|
||||
# Send getvalues request to config service
|
||||
request = ConfigRequest(
|
||||
id=str(uuid.uuid4()),
|
||||
operation='getvalues',
|
||||
type='collections',
|
||||
)
|
||||
|
||||
# Send request and wait for response
|
||||
response = await self.send_config_request(request)
|
||||
|
||||
# Parse collections from response
|
||||
collections = []
|
||||
for key, value_json in response.values.items():
|
||||
if ":" in key:
|
||||
coll_user, collection = key.split(":", 1)
|
||||
if coll_user == user:
|
||||
metadata = json.loads(value_json)
|
||||
collections.append(CollectionMetadata(**metadata))
|
||||
|
||||
# Apply tag filtering in-memory (as before)
|
||||
if tag_filter:
|
||||
collections = [c for c in collections if any(tag in c.tags for tag in tag_filter)]
|
||||
|
||||
# Apply limit
|
||||
if limit:
|
||||
collections = collections[:limit]
|
||||
|
||||
return collections
|
||||
|
||||
async def send_config_request(self, request):
|
||||
"""Send config request and wait for response"""
|
||||
event = asyncio.Event()
|
||||
self.pending_config_requests[request.id] = event
|
||||
|
||||
await self.config_request_producer.send(request)
|
||||
await event.wait()
|
||||
|
||||
return self.pending_config_requests.pop(request.id + "_response")
|
||||
|
||||
async def on_config_response(self, message, consumer, flow):
|
||||
"""Handle config response"""
|
||||
response = message.value()
|
||||
if response.id in self.pending_config_requests:
|
||||
self.pending_config_requests[response.id + "_response"] = response
|
||||
self.pending_config_requests[response.id].set()
|
||||
```
|
||||
|
||||
**`update_collection` को संशोधित करें (पंक्तियाँ 182-312):**
|
||||
```python
|
||||
async def update_collection(self, user, collection, name, description, tags):
|
||||
"""Update collection via config service"""
|
||||
# Create metadata
|
||||
metadata = CollectionMetadata(
|
||||
user=user,
|
||||
collection=collection,
|
||||
name=name,
|
||||
description=description,
|
||||
tags=tags,
|
||||
)
|
||||
|
||||
# Send put request to config service
|
||||
request = ConfigRequest(
|
||||
id=str(uuid.uuid4()),
|
||||
operation='put',
|
||||
type='collections',
|
||||
key=f'{user}:{collection}',
|
||||
value=json.dumps(metadata.to_dict()),
|
||||
)
|
||||
|
||||
response = await self.send_config_request(request)
|
||||
|
||||
if response.error:
|
||||
raise RuntimeError(f"Config update failed: {response.error.message}")
|
||||
|
||||
# Config service will trigger config push automatically
|
||||
# Storage services will receive update and create collections
|
||||
```
|
||||
|
||||
**`delete_collection` में संशोधन करें (पंक्तियाँ 314-398):**
|
||||
```python
|
||||
async def delete_collection(self, user, collection):
|
||||
"""Delete collection via config service"""
|
||||
# Send delete request to config service
|
||||
request = ConfigRequest(
|
||||
id=str(uuid.uuid4()),
|
||||
operation='delete',
|
||||
type='collections',
|
||||
key=f'{user}:{collection}',
|
||||
)
|
||||
|
||||
response = await self.send_config_request(request)
|
||||
|
||||
if response.error:
|
||||
raise RuntimeError(f"Config delete failed: {response.error.message}")
|
||||
|
||||
# Config service will trigger config push automatically
|
||||
# Storage services will receive update and delete collections
|
||||
```
|
||||
|
||||
**संग्रह मेटाडेटा प्रारूप:**
|
||||
कॉन्फ़िगरेशन तालिका में इस प्रकार संग्रहीत: `class='collections', key='user:collection'`
|
||||
मान JSON-सीरियलाइज़्ड CollectionMetadata है (समय-मुद्रांकन फ़ील्ड के बिना)
|
||||
फ़ील्ड: `user`, `collection`, `name`, `description`, `tags`
|
||||
उदाहरण: `class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'`
|
||||
|
||||
#### परिवर्तन 8: लाइब्रेरियन सेवा - स्टोरेज मैनेजमेंट इंफ्रास्ट्रक्चर को हटाएं
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/librarian/service.py`
|
||||
|
||||
**हटाएं:**
|
||||
स्टोरेज मैनेजमेंट प्रोड्यूसर (पंक्ति 173-190):
|
||||
`vector_storage_management_producer`
|
||||
`object_storage_management_producer`
|
||||
`triples_storage_management_producer`
|
||||
स्टोरेज रिस्पांस कंज्यूमर (पंक्ति 192-201)
|
||||
`on_storage_response` हैंडलर (पंक्ति 467-473)
|
||||
|
||||
**संशोधित करें:**
|
||||
CollectionManager इनिशियलाइज़ेशन (पंक्ति 215-224) - स्टोरेज प्रोड्यूसर पैरामीटर हटाएं
|
||||
|
||||
**ध्यान दें:** बाहरी संग्रह एपीआई अपरिवर्तित रहता है:
|
||||
`list-collections`
|
||||
`update-collection`
|
||||
`delete-collection`
|
||||
|
||||
#### परिवर्तन 9: LibraryTableStore से Collections टेबल को हटाएं
|
||||
**फ़ाइल:** `trustgraph-flow/trustgraph/tables/library.py`
|
||||
|
||||
**हटाएं:**
|
||||
Collections टेबल CREATE स्टेटमेंट (पंक्ति 114-127)
|
||||
Collections तैयार स्टेटमेंट (पंक्ति 205-240)
|
||||
सभी संग्रह विधियाँ (पंक्ति 578-717):
|
||||
`ensure_collection_exists`
|
||||
`list_collections`
|
||||
`update_collection`
|
||||
`delete_collection`
|
||||
`get_collection`
|
||||
`create_collection`
|
||||
|
||||
**तर्क:**
|
||||
संग्रह अब कॉन्फ़िगरेशन तालिका में संग्रहीत हैं।
|
||||
परिवर्तन स्वीकार्य है - डेटा माइग्रेशन की आवश्यकता नहीं है।
|
||||
लाइब्रेरियन सेवा को काफी सरल बनाता है।
|
||||
|
||||
#### परिवर्तन 10: स्टोरेज सेवाएं - कॉन्फ़िगरेशन-आधारित संग्रह प्रबंधन ✅ पूर्ण
|
||||
|
||||
**स्थिति:** सभी 11 स्टोरेज बैकएंड को `CollectionConfigHandler` का उपयोग करने के लिए माइग्रेट किया गया है।
|
||||
|
||||
**प्रभावित सेवाएं (कुल 11):**
|
||||
दस्तावेज़ एम्बेडिंग: मिलवस, पाइनकोन, क्यूड्रांट
|
||||
ग्राफ एम्बेडिंग: मिलवस, पाइनकोन, क्यूड्रांट
|
||||
ऑब्जेक्ट स्टोरेज: कैसेंड्रा
|
||||
ट्रिपल स्टोरेज: कैसेंड्रा, फाल्कोडीबी, मेमग्राफ, नियो4जे
|
||||
|
||||
**फाइलें:**
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/pinecone/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/doc_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/graph_embeddings/milvus/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/graph_embeddings/pinecone/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/graph_embeddings/qdrant/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/objects/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/triples/cassandra/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/triples/falkordb/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/triples/memgraph/write.py`
|
||||
`trustgraph-flow/trustgraph/storage/triples/neo4j/write.py`
|
||||
|
||||
**कार्यान्वयन पैटर्न (सभी सेवाएं):**
|
||||
|
||||
1. **`__init__` में कॉन्फ़िगरेशन हैंडलर पंजीकृत करें:**
|
||||
```python
|
||||
# Add after AsyncProcessor initialization
|
||||
self.register_config_handler(self.on_collection_config)
|
||||
self.known_collections = set() # Track (user, collection) tuples
|
||||
```
|
||||
|
||||
2. **कॉन्फ़िगरेशन हैंडलर को लागू करें:**
|
||||
```python
|
||||
async def on_collection_config(self, config, version):
|
||||
"""Handle collection configuration updates"""
|
||||
logger.info(f"Collection config version: {version}")
|
||||
|
||||
if "collections" not in config:
|
||||
return
|
||||
|
||||
# Parse collections from config
|
||||
# Key format: "user:collection" in config["collections"]
|
||||
config_collections = set()
|
||||
for key in config["collections"].keys():
|
||||
if ":" in key:
|
||||
user, collection = key.split(":", 1)
|
||||
config_collections.add((user, collection))
|
||||
|
||||
# Determine changes
|
||||
to_create = config_collections - self.known_collections
|
||||
to_delete = self.known_collections - config_collections
|
||||
|
||||
# Create new collections (idempotent)
|
||||
for user, collection in to_create:
|
||||
try:
|
||||
await self.create_collection_internal(user, collection)
|
||||
self.known_collections.add((user, collection))
|
||||
logger.info(f"Created collection: {user}/{collection}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to create {user}/{collection}: {e}")
|
||||
|
||||
# Delete removed collections (idempotent)
|
||||
for user, collection in to_delete:
|
||||
try:
|
||||
await self.delete_collection_internal(user, collection)
|
||||
self.known_collections.discard((user, collection))
|
||||
logger.info(f"Deleted collection: {user}/{collection}")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to delete {user}/{collection}: {e}")
|
||||
```
|
||||
|
||||
3. **प्रारंभ में ज्ञात संग्रहों को आरंभीकृत करें:**
|
||||
```python
|
||||
async def start(self):
|
||||
"""Start the processor"""
|
||||
await super().start()
|
||||
await self.sync_known_collections()
|
||||
|
||||
async def sync_known_collections(self):
|
||||
"""Query backend to populate known_collections set"""
|
||||
# Backend-specific implementation:
|
||||
# - Milvus/Pinecone/Qdrant: List collections/indexes matching naming pattern
|
||||
# - Cassandra: Query keyspaces or collection metadata
|
||||
# - Neo4j/Memgraph/FalkorDB: Query CollectionMetadata nodes
|
||||
pass
|
||||
```
|
||||
|
||||
4. **मौजूदा हैंडलर विधियों को पुनर्गठित करें:**
|
||||
```python
|
||||
# Rename and remove response sending:
|
||||
# handle_create_collection → create_collection_internal
|
||||
# handle_delete_collection → delete_collection_internal
|
||||
|
||||
async def create_collection_internal(self, user, collection):
|
||||
"""Create collection (idempotent)"""
|
||||
# Same logic as current handle_create_collection
|
||||
# But remove response producer calls
|
||||
# Handle "already exists" gracefully
|
||||
pass
|
||||
|
||||
async def delete_collection_internal(self, user, collection):
|
||||
"""Delete collection (idempotent)"""
|
||||
# Same logic as current handle_delete_collection
|
||||
# But remove response producer calls
|
||||
# Handle "not found" gracefully
|
||||
pass
|
||||
```
|
||||
|
||||
5. **भंडारण प्रबंधन अवसंरचना को हटाएं:**
|
||||
`self.storage_request_consumer` सेटअप और प्रारंभ को हटाएं
|
||||
`self.storage_response_producer` सेटअप को हटाएं
|
||||
`on_storage_management` डिस्पैचर विधि को हटाएं
|
||||
भंडारण प्रबंधन के लिए मेट्रिक्स को हटाएं
|
||||
इम्पोर्ट को हटाएं: `StorageManagementRequest`, `StorageManagementResponse`
|
||||
|
||||
**बैकएंड-विशिष्ट विचार:**
|
||||
|
||||
**वेक्टर स्टोर (मिलवस, पाइनकोन, क्यूड्रांट):** `known_collections` में लॉजिकल `(user, collection)` को ट्रैक करें, लेकिन प्रत्येक आयाम के लिए कई बैकएंड संग्रह बनाए जा सकते हैं। आलसी निर्माण पैटर्न जारी रखें। हटाने के कार्यों को सभी आयाम वेरिएंट को हटाना चाहिए।
|
||||
|
||||
**कैसेंड्रा ऑब्जेक्ट्स:** संग्रह पंक्ति गुण हैं, संरचनाएं नहीं। कीस्पेस-स्तरीय जानकारी को ट्रैक करें।
|
||||
|
||||
**ग्राफ स्टोर (नियो4जे, मेमग्राफ, फाल्कोर्डबी):** स्टार्टअप पर `CollectionMetadata` नोड्स को क्वेरी करें। सिंक पर मेटाडेटा नोड्स बनाएं/हटाएं।
|
||||
|
||||
**कैसेंड्रा ट्रिपल्स:** संग्रह संचालन के लिए `KnowledgeGraph` एपीआई का उपयोग करें।
|
||||
|
||||
**मुख्य डिज़ाइन बिंदु:**
|
||||
|
||||
**अंतिम स्थिरता:** कोई अनुरोध/प्रतिक्रिया तंत्र नहीं, कॉन्फ़िगरेशन पुश प्रसारित किया जाता है
|
||||
**अपरिवर्तनीयता:** सभी निर्माण/हटाने के संचालन को पुनः प्रयास करना सुरक्षित होना चाहिए
|
||||
**त्रुटि प्रबंधन:** त्रुटियों को लॉग करें लेकिन कॉन्फ़िगरेशन अपडेट को अवरुद्ध न करें
|
||||
**स्व-सुधार:** विफल संचालन अगले कॉन्फ़िगरेशन पुश पर पुनः प्रयास करेंगे
|
||||
**संग्रह कुंजी प्रारूप:** `config["collections"]` में `"user:collection"`
|
||||
|
||||
#### परिवर्तन 11: संग्रह स्कीमा अपडेट करें - टाइमस्टैम्प हटाएं
|
||||
**फ़ाइल:** `trustgraph-base/trustgraph/schema/services/collection.py`
|
||||
|
||||
**संग्रहMetadata (पंक्ति 13-21) को संशोधित करें:**
|
||||
`created_at` और `updated_at` फ़ील्ड को हटाएं:
|
||||
```python
|
||||
class CollectionMetadata(Record):
|
||||
user = String()
|
||||
collection = String()
|
||||
name = String()
|
||||
description = String()
|
||||
tags = Array(String())
|
||||
# Remove: created_at = String()
|
||||
# Remove: updated_at = String()
|
||||
```
|
||||
|
||||
**कलेक्शनमैनेजमेंट रिक्वेस्ट में बदलाव (पंक्ति 25-47):**
|
||||
टाइमस्टैम्प फ़ील्ड हटाएं:
|
||||
```python
|
||||
class CollectionManagementRequest(Record):
|
||||
operation = String()
|
||||
user = String()
|
||||
collection = String()
|
||||
timestamp = String()
|
||||
name = String()
|
||||
description = String()
|
||||
tags = Array(String())
|
||||
# Remove: created_at = String()
|
||||
# Remove: updated_at = String()
|
||||
tag_filter = Array(String())
|
||||
limit = Integer()
|
||||
```
|
||||
|
||||
**तर्क:**
|
||||
टाइमस्टैम्प संग्रह के लिए कोई मूल्य नहीं जोड़ते हैं।
|
||||
कॉन्फ़िगरेशन सेवा अपनी संस्करण ट्रैकिंग बनाए रखती है।
|
||||
स्कीमा को सरल बनाता है और भंडारण को कम करता है।
|
||||
|
||||
#### कॉन्फ़िगरेशन सेवा माइग्रेशन के लाभ
|
||||
|
||||
1. ✅ **हार्डकोडेड स्टोरेज प्रबंधन विषयों को समाप्त करता है** - मल्टी-टेनेंट अवरोध को हल करता है।
|
||||
2. ✅ **सरल समन्वय** - 4+ स्टोरेज प्रतिक्रियाओं के लिए कोई जटिल एसिंक्रोनस प्रतीक्षा नहीं।
|
||||
3. ✅ **अंतिम स्थिरता** - स्टोरेज सेवाएं कॉन्फ़िगरेशन पुश के माध्यम से स्वतंत्र रूप से अपडेट करती हैं।
|
||||
4. ✅ **बेहतर विश्वसनीयता** - गैर-स्थायी अनुरोध/प्रतिक्रिया के विपरीत, लगातार कॉन्फ़िगरेशन पुश।
|
||||
5. ✅ **एकीकृत कॉन्फ़िगरेशन मॉडल** - संग्रह को कॉन्फ़िगरेशन के रूप में माना जाता है।
|
||||
6. ✅ **जटिलता को कम करता है** - ~300 लाइनों के समन्वय कोड को हटाता है।
|
||||
7. ✅ **मल्टी-टेनेंट के लिए तैयार** - कॉन्फ़िगरेशन पहले से ही कीस्पेस के माध्यम से किरायेदार अलगाव का समर्थन करता है।
|
||||
8. ✅ **संस्करण ट्रैकिंग** - कॉन्फ़िगरेशन सेवा संस्करण तंत्र ऑडिट ट्रेल प्रदान करता है।
|
||||
|
||||
## कार्यान्वयन नोट्स
|
||||
|
||||
### पिछड़ा संगतता
|
||||
|
||||
**पैरामीटर परिवर्तन:**
|
||||
CLI पैरामीटर का नाम बदलना एक ब्रेकिंग परिवर्तन है लेकिन स्वीकार्य है (फ़ीचर वर्तमान में गैर-कार्यात्मक है)।
|
||||
सेवाएं पैरामीटर के बिना काम करती हैं (डिफ़ॉल्ट का उपयोग करें)।
|
||||
डिफ़ॉल्ट कीस्पेस संरक्षित हैं: "config", "knowledge", "librarian"
|
||||
डिफ़ॉल्ट कतार: `persistent://tg/config/config`
|
||||
|
||||
**संग्रह प्रबंधन:**
|
||||
**ब्रेकिंग परिवर्तन:** लाइब्रेरियन कीस्पेस से संग्रह तालिका हटा दी गई है।
|
||||
**कोई डेटा माइग्रेशन प्रदान नहीं किया गया है** - इस चरण के लिए स्वीकार्य है।
|
||||
बाहरी संग्रह API अपरिवर्तित है (सूची/अपडेट/हटाने के संचालन)।
|
||||
संग्रह मेटाडेटा प्रारूप को सरल बनाया गया है (टाइमस्टैम्प हटा दिए गए हैं)।
|
||||
|
||||
### परीक्षण आवश्यकताएँ
|
||||
|
||||
**पैरामीटर परीक्षण:**
|
||||
1. सत्यापित करें कि `--config-push-queue` पैरामीटर ग्राफ-एम्बेडिंग सेवा पर काम करता है।
|
||||
2. सत्यापित करें कि `--config-push-queue` पैरामीटर टेक्स्ट-कंप्लीशन सेवा पर काम करता है।
|
||||
3. सत्यापित करें कि `--config-push-queue` पैरामीटर कॉन्फ़िगरेशन सेवा पर काम करता है।
|
||||
4. सत्यापित करें कि `--cassandra-keyspace` पैरामीटर कॉन्फ़िगरेशन सेवा के लिए काम करता है।
|
||||
5. सत्यापित करें कि `--cassandra-keyspace` पैरामीटर कोर सेवा के लिए काम करता है।
|
||||
6. सत्यापित करें कि `--cassandra-keyspace` पैरामीटर लाइब्रेरियन सेवा के लिए काम करता है।
|
||||
7. सत्यापित करें कि सेवाएं पैरामीटर के बिना काम करती हैं (डिफ़ॉल्ट का उपयोग करती हैं)।
|
||||
8. कस्टम कतार नामों और कीस्पेस के साथ मल्टी-टेनेंट परिनियोजन सत्यापित करें।
|
||||
|
||||
**संग्रह प्रबंधन परीक्षण:**
|
||||
9. कॉन्फ़िगरेशन सेवा के माध्यम से `list-collections` ऑपरेशन सत्यापित करें।
|
||||
10. सत्यापित करें कि `update-collection` कॉन्फ़िगरेशन तालिका में बनाता/अपडेट करता है।
|
||||
11. सत्यापित करें कि `delete-collection` कॉन्फ़िगरेशन तालिका से हटाता है।
|
||||
12. सत्यापित करें कि संग्रह अपडेट पर कॉन्फ़िगरेशन पुश ट्रिगर होता है।
|
||||
13. सत्यापित करें कि कॉन्फ़िगरेशन-आधारित स्टोरेज के साथ टैग फ़िल्टरिंग काम करता है।
|
||||
14. सत्यापित करें कि संग्रह ऑपरेशन टाइमस्टैम्प फ़ील्ड के बिना काम करते हैं।
|
||||
|
||||
### मल्टी-टेनेंट परिनियोजन उदाहरण
|
||||
```bash
|
||||
# Tenant: tg-dev
|
||||
graph-embeddings \
|
||||
-p pulsar+ssl://broker:6651 \
|
||||
--pulsar-api-key <KEY> \
|
||||
--config-push-queue persistent://tg-dev/config/config
|
||||
|
||||
config-service \
|
||||
-p pulsar+ssl://broker:6651 \
|
||||
--pulsar-api-key <KEY> \
|
||||
--config-push-queue persistent://tg-dev/config/config \
|
||||
--cassandra-keyspace tg_dev_config
|
||||
```
|
||||
|
||||
## प्रभाव विश्लेषण
|
||||
|
||||
### परिवर्तन 1-2 से प्रभावित सेवाएं (CLI पैरामीटर का नाम बदलना)
|
||||
सभी सेवाएं जो AsyncProcessor या FlowProcessor से विरासत में मिली हैं:
|
||||
config-service
|
||||
cores-service
|
||||
librarian-service
|
||||
graph-embeddings
|
||||
document-embeddings
|
||||
text-completion-* (सभी प्रदाता)
|
||||
extract-* (सभी एक्सट्रैक्टर)
|
||||
query-* (सभी क्वेरी सेवाएं)
|
||||
retrieval-* (सभी RAG सेवाएं)
|
||||
storage-* (सभी स्टोरेज सेवाएं)
|
||||
और 20+ से अधिक सेवाएं
|
||||
|
||||
### परिवर्तन 3-6 से प्रभावित सेवाएं (कैसेंड्रा कीस्पेस)
|
||||
config-service
|
||||
cores-service
|
||||
librarian-service
|
||||
|
||||
### परिवर्तन 7-11 से प्रभावित सेवाएं (संग्रह प्रबंधन)
|
||||
|
||||
**तत्काल परिवर्तन:**
|
||||
librarian-service (collection_manager.py, service.py)
|
||||
tables/library.py (संग्रह तालिका को हटाना)
|
||||
schema/services/collection.py (टाइमस्टैम्प को हटाना)
|
||||
|
||||
**पूरे हुए परिवर्तन (परिवर्तन 10):** ✅
|
||||
सभी स्टोरेज सेवाएं (कुल 11) - संग्रह अपडेट के लिए कॉन्फ़िगरेशन पुश के माध्यम से `CollectionConfigHandler` में माइग्रेट किया गया
|
||||
`storage.py` से स्टोरेज प्रबंधन स्कीमा को हटाया गया
|
||||
|
||||
## भविष्य के विचार
|
||||
|
||||
### प्रति-उपयोगकर्ता कीस्पेस मॉडल
|
||||
|
||||
कुछ सेवाएं **प्रति-उपयोगकर्ता कीस्पेस** गतिशील रूप से उपयोग करती हैं, जहां प्रत्येक उपयोगकर्ता का अपना कैसेंड्रा कीस्पेस होता है:
|
||||
|
||||
**प्रति-उपयोगकर्ता कीस्पेस वाली सेवाएं:**
|
||||
1. **ट्रिपल्स क्वेरी सर्विस** (`trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65`)
|
||||
`keyspace=query.user` का उपयोग करता है
|
||||
2. **ऑब्जेक्ट्स क्वेरी सर्विस** (`trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479`)
|
||||
`keyspace=self.sanitize_name(user)` का उपयोग करता है
|
||||
3. **नॉलेज ग्राफ डायरेक्ट एक्सेस** (`trustgraph-flow/trustgraph/direct/cassandra_kg.py:18`)
|
||||
डिफ़ॉल्ट पैरामीटर `keyspace="trustgraph"`
|
||||
|
||||
**स्थिति:** ये इस विनिर्देश में **बदले नहीं गए** हैं।
|
||||
|
||||
**भविष्य की समीक्षा आवश्यक:**
|
||||
मूल्यांकन करें कि क्या प्रति-उपयोगकर्ता कीस्पेस मॉडल किरायेदार अलगाव के मुद्दे बनाता है
|
||||
इस पर विचार करें कि क्या मल्टी-टेनेन्ट डिप्लॉयमेंट को कीस्पेस उपसर्ग पैटर्न (जैसे, `tenant_a_user1`) की आवश्यकता है
|
||||
किरायेदारों में संभावित उपयोगकर्ता आईडी टकराव के लिए समीक्षा करें
|
||||
मूल्यांकन करें कि क्या प्रति किरायेदार एकल साझा कीस्पेस उपयोगकर्ता-आधारित पंक्ति अलगाव के साथ अधिक उपयुक्त है
|
||||
|
||||
**नोट:** यह वर्तमान मल्टी-टेनेन्ट कार्यान्वयन को अवरुद्ध नहीं करता है, लेकिन उत्पादन मल्टी-टेनेन्ट डिप्लॉयमेंट से पहले इसकी समीक्षा की जानी चाहिए।
|
||||
|
||||
## कार्यान्वयन चरण
|
||||
|
||||
### चरण 1: पैरामीटर सुधार (परिवर्तन 1-6)
|
||||
`--config-push-queue` पैरामीटर नामकरण को ठीक करें
|
||||
`--cassandra-keyspace` पैरामीटर समर्थन जोड़ें
|
||||
**परिणाम:** मल्टी-टेनेन्ट कतार और कीस्पेस कॉन्फ़िगरेशन सक्षम
|
||||
|
||||
### चरण 2: संग्रह प्रबंधन माइग्रेशन (परिवर्तन 7-9, 11)
|
||||
संग्रह स्टोरेज को कॉन्फ़िगरेशन सेवा में माइग्रेट करें
|
||||
लाइब्रेरियन से संग्रह तालिका को हटा दें
|
||||
संग्रह स्कीमा को अपडेट करें (टाइमस्टैम्प हटाएं)
|
||||
**परिणाम:** हार्डकोडेड स्टोरेज प्रबंधन विषयों को समाप्त करता है, लाइब्रेरियन को सरल बनाता है
|
||||
|
||||
### चरण 3: स्टोरेज सर्विस अपडेट (परिवर्तन 10) ✅ पूर्ण
|
||||
सभी स्टोरेज सेवाओं को `CollectionConfigHandler` के माध्यम से संग्रह के लिए कॉन्फ़िगरेशन पुश का उपयोग करने के लिए अपडेट किया गया
|
||||
स्टोरेज प्रबंधन अनुरोध/प्रतिक्रिया बुनियादी ढांचे को हटा दिया गया
|
||||
विरासत स्कीमा परिभाषाओं को हटा दिया गया
|
||||
**परिणाम:** कॉन्फ़िगरेशन-आधारित संग्रह प्रबंधन प्राप्त हुआ
|
||||
|
||||
## संदर्भ
|
||||
GitHub मुद्दा: https://github.com/trustgraph-ai/trustgraph/issues/582
|
||||
संबंधित फाइलें:
|
||||
`trustgraph-base/trustgraph/base/async_processor.py`
|
||||
`trustgraph-base/trustgraph/base/cassandra_config.py`
|
||||
`trustgraph-base/trustgraph/schema/core/topic.py`
|
||||
`trustgraph-base/trustgraph/schema/services/collection.py`
|
||||
`trustgraph-flow/trustgraph/config/service/service.py`
|
||||
`trustgraph-flow/trustgraph/cores/service.py`
|
||||
`trustgraph-flow/trustgraph/librarian/service.py`
|
||||
`trustgraph-flow/trustgraph/librarian/collection_manager.py`
|
||||
`trustgraph-flow/trustgraph/tables/library.py`
|
||||
Loading…
Add table
Add a link
Reference in a new issue