trustgraph/docs/tech-specs/multi-tenant-support.pt.md
Alex Jenkins 8954fa3ad7 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.
2026-04-14 12:08:32 +01:00

31 KiB

layout title parent
default Especificação Técnica: Suporte para Multi-Tenancy Portuguese (Beta)

Especificação Técnica: Suporte para Multi-Tenancy

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.

Visão Geral

Habilite implantações multi-tenant corrigindo incompatibilidades de nomes de parâmetros que impedem a personalização da fila e adicionando parametrização do keyspace do Cassandra.

Contexto da Arquitetura

Resolução de Filas Baseada em Fluxo

O sistema TrustGraph usa uma arquitetura baseada em fluxo para a resolução dinâmica de filas, que suporta inerentemente o multi-tenancy:

As Definições de Fluxo são armazenadas no Cassandra e especificam os nomes das filas por meio de definições de interface. Os nomes das filas usam modelos com variáveis {id} que são substituídas pelos IDs das instâncias de fluxo. Os serviços resolvem dinamicamente as filas consultando as configurações de fluxo no momento da solicitação. Cada tenant pode ter fluxos únicos com nomes de fila diferentes, proporcionando isolamento.

Exemplo de definição de interface de fluxo:

{
  "interfaces": {
    "triples-store": "persistent://tg/flow/triples-store:{id}",
    "graph-embeddings-store": "persistent://tg/flow/graph-embeddings-store:{id}"
  }
}

Quando o tenant A inicia o fluxo tenant-a-prod e o tenant B inicia o fluxo tenant-b-prod, eles automaticamente recebem filas isoladas: persistent://tg/flow/triples-store:tenant-a-prod persistent://tg/flow/triples-store:tenant-b-prod

Serviços corretamente projetados para multi-tenancy: Knowledge Management (cores) - Resolve dinamicamente as filas a partir da configuração do fluxo passada nas requisições

Serviços que precisam de correções: 🔴 Config Service - Incompatibilidade no nome do parâmetro impede a personalização da fila 🔴 Librarian Service - Tópicos de gerenciamento de armazenamento codificados (discutido abaixo) 🔴 Todos os Serviços - Não é possível personalizar o keyspace do Cassandra

Declaração do Problema

Problema #1: Incompatibilidade no Nome do Parâmetro no AsyncProcessor

CLI define: --config-queue (nomeação pouco clara) Argparse converte para: config_queue (no dicionário de parâmetros) Código procura por: config_push_queue Resultado: O parâmetro é ignorado, usa o valor padrão de persistent://tg/config/config Impacto: Afeta todos os 32+ serviços que herdam do AsyncProcessor Bloqueia: Impossibilita o uso de filas de configuração específicas do tenant em implantações multi-tenant Solução: Renomear o parâmetro da CLI para --config-push-queue para maior clareza (alteração disruptiva aceitável, já que o recurso está atualmente com defeito)

Problema #2: Incompatibilidade no Nome do Parâmetro no Config Service

CLI define: --push-queue (nomeação ambígua) Argparse converte para: push_queue (no dicionário de parâmetros) Código procura por: config_push_queue Resultado: O parâmetro é ignorado Impacto: O Config service não pode usar uma fila de push personalizada Solução: Renomear o parâmetro da CLI para --config-push-queue para consistência e clareza (alteração disruptiva aceitável)

Problema #3: Keyspace do Cassandra Codificado

Atual: Keyspace codificado como "config", "knowledge", "librarian" em vários serviços Resultado: Impossibilita a personalização do keyspace para implantações multi-tenant Impacto: Serviços Config, cores e librarian Bloqueia: Múltiplos tenants não podem usar keyspaces separados do Cassandra

Problema #4: Arquitetura de Gerenciamento de Coleções CONCLUÍDO

Anterior: Coleções armazenadas no keyspace do librarian do Cassandra em uma tabela de coleções separada Anterior: O librarian usava 4 tópicos de gerenciamento de armazenamento codificados para coordenar a criação/exclusão de coleções: vector_storage_management_topic object_storage_management_topic triples_storage_management_topic storage_management_response_topic Problemas (Resolvidos): Tópicos codificados não podiam ser personalizados para implantações multi-tenant Coordenação assíncrona complexa entre o librarian e 4+ serviços de armazenamento Tabela separada do Cassandra e infraestrutura de gerenciamento Filas de requisição/resposta não persistentes para operações críticas Solução Implementada: Migrou as coleções para o armazenamento do serviço de configuração, usa push de configuração para distribuição Status: Todos os backends de armazenamento migrados para o padrão CollectionConfigHandler

Solução

Esta especificação aborda os problemas #1, #2, #3 e #4.

Parte 1: Corrigir Incompatibilidades no Nome do Parâmetro

Alteração 1: Classe Base AsyncProcessor - Renomear Parâmetro da CLI

Arquivo: trustgraph-base/trustgraph/base/async_processor.py Linha: 260-264

Atual:

parser.add_argument(
    '--config-queue',
    default=default_config_queue,
    help=f'Config push queue {default_config_queue}',
)

Corrigido:

parser.add_argument(
    '--config-push-queue',
    default=default_config_queue,
    help=f'Config push queue (default: {default_config_queue})',
)

Justificativa: Nomenclatura mais clara e explícita Coincide com o nome da variável interna config_push_queue Mudança disruptiva aceitável, já que a funcionalidade está atualmente inativa Não é necessária nenhuma alteração no código em params.get() - ele já procura pelo nome correto

Mudança 2: Serviço de Configuração - Renomear Parâmetro da CLI

Arquivo: trustgraph-flow/trustgraph/config/service/service.py Linha: 276-279

Atual:

parser.add_argument(
    '--push-queue',
    default=default_config_push_queue,
    help=f'Config push queue (default: {default_config_push_queue})'
)

Corrigido:

parser.add_argument(
    '--config-push-queue',
    default=default_config_push_queue,
    help=f'Config push queue (default: {default_config_push_queue})'
)

Justificativa: Nomes mais claros - "config-push-queue" é mais explícito do que apenas "push-queue". Compatível com o nome da variável interna config_push_queue. Consistente com o parâmetro --config-push-queue do AsyncProcessor. Mudança disruptiva aceitável, já que o recurso está atualmente inativo. Nenhuma alteração de código necessária em params.get() - ele já procura pelo nome correto.

Parte 2: Adicionar Parametrização do Keyspace do Cassandra

Mudança 3: Adicionar Parâmetro de Keyspace ao Módulo cassandra_config

Arquivo: trustgraph-base/trustgraph/base/cassandra_config.py

Adicionar argumento de linha de comando (na função add_cassandra_args()):

parser.add_argument(
    '--cassandra-keyspace',
    default=None,
    help='Cassandra keyspace (default: service-specific)'
)

Adicionar suporte para variáveis de ambiente (na função resolve_cassandra_config()):

keyspace = params.get(
    "cassandra_keyspace",
    os.environ.get("CASSANDRA_KEYSPACE")
)

Atualizar o valor de retorno de resolve_cassandra_config(): Atualmente retorna: (hosts, username, password) Alterar para retornar: (hosts, username, password, keyspace)

Justificativa: Consistente com o padrão de configuração existente do Cassandra Disponível para todos os serviços via add_cassandra_args() Suporta configuração via linha de comando e variáveis de ambiente

Mudança 4: Serviço de Configuração - Usar Keyspace Parametrizados

Arquivo: trustgraph-flow/trustgraph/config/service/service.py

Linha 30 - Remover o keyspace codificado:

# DELETE THIS LINE:
keyspace = "config"

Linhas 69-73 - Atualização da resolução da configuração do Cassandra:

Atual:

cassandra_host, cassandra_username, cassandra_password = \
    resolve_cassandra_config(params)

Corrigido:

cassandra_host, cassandra_username, cassandra_password, keyspace = \
    resolve_cassandra_config(params, default_keyspace="config")

Justificativa: Mantém a compatibilidade com versões anteriores, utilizando "config" como padrão. Permite a substituição através de --cassandra-keyspace ou CASSANDRA_KEYSPACE.

Mudança 5: Cores/Serviço de Conhecimento - Utilizar Chaves de Espaço de Chaves Parametrizadas

Arquivo: trustgraph-flow/trustgraph/cores/service.py

Linha 37 - Remover o espaço de chaves codificado:

# DELETE THIS LINE:
keyspace = "knowledge"

Atualização da resolução de configuração do Cassandra (localização semelhante ao serviço de configuração):

cassandra_host, cassandra_username, cassandra_password, keyspace = \
    resolve_cassandra_config(params, default_keyspace="knowledge")

Mudança 6: Serviço de Bibliotecário - Use Chaves de Espaço de Chaves Parametrizadas

Arquivo: trustgraph-flow/trustgraph/librarian/service.py

Linha 51 - Remova a chave de espaço de chaves codificada:

# DELETE THIS LINE:
keyspace = "librarian"

Atualização da resolução de configuração do Cassandra (localização semelhante ao serviço de configuração):

cassandra_host, cassandra_username, cassandra_password, keyspace = \
    resolve_cassandra_config(params, default_keyspace="librarian")

Parte 3: Migrar o Gerenciamento de Coleções para o Serviço de Configuração

Visão Geral

Migrar as coleções do keyspace do Cassandra librarian para o armazenamento do serviço de configuração. Isso elimina os tópicos de gerenciamento de armazenamento codificados e simplifica a arquitetura, utilizando o mecanismo de push de configuração existente para distribuição.

Arquitetura Atual

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

Nova Arquitetura

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

Mudança 7: Gerenciador de Coleções - Usar API do Serviço de Configuração

Arquivo: trustgraph-flow/trustgraph/librarian/collection_manager.py

Remover: Uso de LibraryTableStore (Linhas 33, 40-41) Inicialização de produtores de gerenciamento de armazenamento (Linhas 86-140) Método on_storage_response (Linhas 400-430) Rastreamento de pending_deletions (Linhas 57, 90-96 e uso em todo o código)

Adicionar: Cliente do serviço de configuração para chamadas de API (padrão de solicitação/resposta)

Configuração do Cliente:

# 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

Modificar list_collections (Linhas 145-180):

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()

Modificar update_collection (Linhas 182-312):

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

Modificar delete_collection (Linhas 314-398):

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

Formato de Metadados de Coleção: Armazenado na tabela de configuração como: class='collections', key='user:collection' O valor é uma CollectionMetadata serializada em JSON (sem campos de timestamp) Campos: user, collection, name, description, tags Exemplo: class='collections', key='alice:my-docs', value='{"user":"alice","collection":"my-docs","name":"My Documents","description":"...","tags":["work"]}'

Mudança 8: Serviço de Bibliotecário - Remover a Infraestrutura de Gerenciamento de Armazenamento

Arquivo: trustgraph-flow/trustgraph/librarian/service.py

Remover: Produtores de gerenciamento de armazenamento (Linhas 173-190): vector_storage_management_producer object_storage_management_producer triples_storage_management_producer Consumidor de resposta de armazenamento (Linhas 192-201) Manipulador on_storage_response (Linhas 467-473)

Modificar: Inicialização do CollectionManager (Linhas 215-224) - remover os parâmetros do produtor de armazenamento

Observação: A API externa de coleções permanece inalterada: list-collections update-collection delete-collection

Mudança 9: Remover a Tabela de Coleções do LibraryTableStore

Arquivo: trustgraph-flow/trustgraph/tables/library.py

Excluir: Instrução CREATE da tabela de coleções (Linhas 114-127) Prepared statements de coleções (Linhas 205-240) Todos os métodos de coleção (Linhas 578-717): ensure_collection_exists list_collections update_collection delete_collection get_collection create_collection

Justificativa: As coleções agora são armazenadas na tabela de configuração Mudança disruptiva aceitável - nenhuma migração de dados necessária Simplifica significativamente o serviço de bibliotecário

Mudança 10: Serviços de Armazenamento - Gerenciamento de Coleção Baseado em Configuração CONCLUÍDO

Status: Todos os 11 backends de armazenamento foram migrados para usar CollectionConfigHandler.

Serviços Afetados (11 no total): Embeddings de documentos: milvus, pinecone, qdrant Embeddings de grafos: milvus, pinecone, qdrant Armazenamento de objetos: cassandra Armazenamento de triplas: cassandra, falkordb, memgraph, neo4j

Arquivos: 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

Padrão de Implementação (todos os serviços):

  1. Registrar o manipulador de configuração em __init__:
# Add after AsyncProcessor initialization
self.register_config_handler(self.on_collection_config)
self.known_collections = set()  # Track (user, collection) tuples
  1. Implementar o gerenciador de configuração:
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}")
  1. Inicialize as coleções conhecidas na inicialização:
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
  1. Refatore os métodos de tratamento existentes:
# 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
  1. Remover a infraestrutura de gerenciamento de armazenamento: Remover a configuração e inicialização de self.storage_request_consumer Remover a configuração de self.storage_response_producer Remover o método de dispatcher de on_storage_management Remover as métricas para o gerenciamento de armazenamento Remover as importações: StorageManagementRequest, StorageManagementResponse

Considerações Específicas para o Backend:

Bancos de dados vetoriais (Milvus, Pinecone, Qdrant): Rastrear a lógica (user, collection) em known_collections, mas pode criar múltiplas coleções de backend por dimensão. Continuar o padrão de criação preguiçosa. As operações de exclusão devem remover todas as variantes de dimensão.

Cassandra Objects: As coleções são propriedades de linha, não estruturas. Rastrear informações no nível do keyspace.

Bancos de dados de grafos (Neo4j, Memgraph, FalkorDB): Consultar nós CollectionMetadata na inicialização. Criar/excluir nós de metadados na sincronização.

Cassandra Triples: Usar a API KnowledgeGraph para operações de coleção.

Pontos-Chave do Design:

Consistência eventual: Não há mecanismo de solicitação/resposta, o envio de configuração é transmitido. Idempotência: Todas as operações de criação/exclusão devem ser seguras para serem repetidas. Tratamento de erros: Registrar erros, mas não bloquear as atualizações de configuração. Autorreparação: As operações com falha serão repetidas na próxima atualização de configuração. Formato da chave da coleção: "user:collection" em config["collections"]

Mudança 11: Atualizar o Esquema da Coleção - Remover Timestamps

Arquivo: trustgraph-base/trustgraph/schema/services/collection.py

Modificar CollectionMetadata (Linhas 13-21): Remover os campos created_at e updated_at:

class CollectionMetadata(Record):
    user = String()
    collection = String()
    name = String()
    description = String()
    tags = Array(String())
    # Remove: created_at = String()
    # Remove: updated_at = String()

Modificar CollectionManagementRequest (linhas 25-47): Remover campos de timestamp:

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()

Justificativa: Os carimbos de data e hora não agregam valor para coleções. O serviço de configuração mantém seu próprio rastreamento de versão. Simplifica o esquema e reduz o armazenamento.

Benefícios da Migração do Serviço de Configuração

  1. Elimina tópicos de gerenciamento de armazenamento codificados - Resolve o bloqueio multi-inquilino.
  2. Coordenação mais simples - Sem espera assíncrona complexa por 4 ou mais respostas de armazenamento.
  3. Consistência eventual - Os serviços de armazenamento são atualizados independentemente por meio de push de configuração.
  4. Melhor confiabilidade - Push de configuração persistente versus solicitação/resposta não persistente.
  5. Modelo de configuração unificado - Coleções tratadas como configuração.
  6. Reduz a complexidade - Remove aproximadamente 300 linhas de código de coordenação.
  7. Pronto para multi-inquilino - A configuração já suporta o isolamento de inquilinos por meio de keyspace.
  8. Rastreamento de versão - O mecanismo de versão do serviço de configuração fornece um histórico de auditoria.

Notas de Implementação

Compatibilidade com versões anteriores

Alterações de parâmetros: As alterações de nome dos parâmetros da CLI são alterações disruptivas, mas aceitáveis (o recurso atualmente não está funcional). Os serviços funcionam sem parâmetros (use os padrões). Keyspaces padrão preservados: "config", "knowledge", "librarian". Fila padrão: persistent://tg/config/config

Gerenciamento de coleções: Alteração disruptiva: A tabela de coleções foi removida do keyspace librarian. Nenhuma migração de dados fornecida - aceitável para esta fase. A API de coleção externa não foi alterada (operações de listagem, atualização e exclusão). O formato de metadados da coleção foi simplificado (os carimbos de data e hora foram removidos).

Requisitos de teste

Teste de parâmetros:

  1. Verificar se o parâmetro --config-push-queue funciona no serviço graph-embeddings.
  2. Verificar se o parâmetro --config-push-queue funciona no serviço text-completion.
  3. Verificar se o parâmetro --config-push-queue funciona no serviço de configuração.
  4. Verificar se o parâmetro --cassandra-keyspace funciona para o serviço de configuração.
  5. Verificar se o parâmetro --cassandra-keyspace funciona para o serviço cores.
  6. Verificar se o parâmetro --cassandra-keyspace funciona para o serviço librarian.
  7. Verificar se os serviços funcionam sem parâmetros (usa os padrões).
  8. Verificar a implantação multi-inquilino com nomes de fila e keyspace personalizados.

Teste de gerenciamento de coleções: 9. Verificar a operação list-collections por meio do serviço de configuração. 10. Verificar se update-collection cria/atualiza na tabela de configuração. 11. Verificar se delete-collection remove da tabela de configuração. 12. Verificar se o push de configuração é acionado em atualizações de coleção. 13. Verificar se a filtragem de tags funciona com armazenamento baseado em configuração. 14. Verificar se as operações de coleção funcionam sem campos de carimbo de data e hora.

Exemplo de implantação multi-inquilino

# 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

Análise de Impacto

Serviços Afetados pela Alteração 1-2 (Renomeação de Parâmetro da CLI)

Todos os serviços que herdam de AsyncProcessor ou FlowProcessor: config-service cores-service librarian-service graph-embeddings document-embeddings text-completion-* (todos os provedores) extract-* (todos os extractors) query-* (todos os serviços de consulta) retrieval-* (todos os serviços RAG) storage-* (todos os serviços de armazenamento) E mais 20 serviços

Serviços Afetados pelas Alterações 3-6 (Keyspace do Cassandra)

config-service cores-service librarian-service

Serviços Afetados pelas Alterações 7-11 (Gerenciamento de Coleções)

Alterações Imediatas: librarian-service (collection_manager.py, service.py) tables/library.py (remoção da tabela de coleções) schema/services/collection.py (remoção do timestamp)

Alterações Concluídas (Alteração 10): Todos os serviços de armazenamento (11 no total) - migrados para o push de configuração para atualizações de coleções via CollectionConfigHandler Esquema de gerenciamento de armazenamento removido de storage.py

Considerações Futuras

Modelo de Keyspace por Usuário

Alguns serviços usam keyspaces por usuário dinamicamente, onde cada usuário recebe seu próprio keyspace do Cassandra:

Serviços com keyspaces por usuário:

  1. Triples Query Service (trustgraph-flow/trustgraph/query/triples/cassandra/service.py:65) Usa keyspace=query.user
  2. Objects Query Service (trustgraph-flow/trustgraph/query/objects/cassandra/service.py:479) Usa keyspace=self.sanitize_name(user)
  3. KnowledgeGraph Direct Access (trustgraph-flow/trustgraph/direct/cassandra_kg.py:18) Parâmetro padrão keyspace="trustgraph"

Status: Estes não são modificados nesta especificação.

Revisão Futura Necessária: Avaliar se o modelo de keyspace por usuário cria problemas de isolamento de locatários Considerar se as implementações multi-locatário precisam de padrões de prefixo de keyspace (por exemplo, tenant_a_user1) Revisar para possíveis colisões de ID de usuário entre locatários Avaliar se um keyspace compartilhado único por locatário com isolamento de linha baseado em usuário é preferível

Observação: Isso não impede a implementação multi-locatário atual, mas deve ser revisado antes das implementações multi-locatário de produção.

Fases de Implementação

Fase 1: Correções de Parâmetros (Alterações 1-6)

Corrigir a nomenclatura do parâmetro --config-push-queue Adicionar suporte ao parâmetro --cassandra-keyspace Resultado: Configuração de fila e keyspace multi-locatário habilitada

Fase 2: Migração do Gerenciamento de Coleções (Alterações 7-9, 11)

Migrar o armazenamento de coleções para o serviço de configuração Remover a tabela de coleções do librarian Atualizar o esquema de coleção (remover timestamps) Resultado: Elimina tópicos de gerenciamento de armazenamento codificados, simplifica o librarian

Fase 3: Atualizações do Serviço de Armazenamento (Alteração 10) CONCLUÍDA

Atualizados todos os serviços de armazenamento para usar o push de configuração para coleções via CollectionConfigHandler Removida a infraestrutura de solicitação/resposta de gerenciamento de armazenamento Removidas as definições de esquema legadas Resultado: Gerenciamento de coleções baseado em configuração completo alcançado

Referências

GitHub Issue: https://github.com/trustgraph-ai/trustgraph/issues/582 Arquivos Relacionados: 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