Pular para conteúdo

Connectors

Um connector representa a integracao com um servico externo: gateways de pagamento, APIs de terceiros, plataformas de analytics, bridges com outros LMS. O MIDDAG fornece um modelo padronizado para credenciais, health check e registro de tipos.

O sistema de connectors e a Core Capability CC-02 (core.connectors) do framework (ADR-607).


Conceito

Connectors resolvem tres problemas:

  1. Catalogo padronizado -- a plataforma sabe quais servicos externos estao disponiveis e em que estado.
  2. Credenciais declarativas -- cada connector declara os campos necessarios para configuracao, sem hardcoding.
  3. Health check uniforme -- monitoramento de conectividade integrado ao framework.

Quick example

Implementar um connector para enviar SMS via Twilio:

namespace local_meuplugin\extensions\notifications\connector;

use local_middag\framework\contract\connector_interface;

final class twilio_connector implements connector_interface
{
    public function __construct(
        private readonly string $account_sid,
        private readonly string $auth_token,
        private readonly string $from_number,
    ) {}

    public function get_type(): string
    {
        return 'twilio';
    }

    public function get_name(): string
    {
        return 'Twilio SMS';
    }

    public function get_extension(): string
    {
        return 'notifications';
    }

    public function health_check(): bool
    {
        try {
            // Tenta autenticar na API do Twilio.
            $response = $this->call_api('/2010-04-01/Accounts/' . $this->account_sid . '.json');
            return $response->status === 'active';
        } catch (\Throwable) {
            return false;
        }
    }

    public function get_credential_fields(): array
    {
        return [
            ['key' => 'account_sid', 'label' => 'Account SID', 'type' => 'text'],
            ['key' => 'auth_token',  'label' => 'Auth Token',  'type' => 'password'],
            ['key' => 'from_number', 'label' => 'From Number',  'type' => 'text'],
        ];
    }
}

API reference

connector_interface

Contract que todo connector deve implementar:

Metodo Retorno Descricao
get_type() string Slug unico do tipo (ex: 'twilio', 'woocommerce', 'bigquery')
get_name() string Nome legivel para exibicao na UI
get_extension() string Slug da extension que possui este connector
health_check() bool Testa conectividade com as credenciais configuradas
get_credential_fields() list<array{key, label, type}> Campos de credencial necessarios para configuracao

Os campos de credencial suportam os tipos 'text', 'password', 'url' e 'select'.

connector_registry_interface

Registry central que gerencia todos os connectors registrados:

Metodo Retorno Descricao
register($connector) void Registra um connector type
get($type) ?connector_interface Retorna connector pelo slug, ou null se inexistente
all() array<string, connector_interface> Todos os connectors registrados, indexados por slug
for_extension($extension) list<connector_interface> Connectors de uma extension especifica

Registro no boot()

Extensions registram seus connectors durante o boot():

namespace local_meuplugin\extensions\notifications;

use local_middag\base\extension;
use local_middag\framework\contract\connector_registry_interface;

class notifications_extension extends extension
{
    public function boot(): void
    {
        $registry = $this->container->get(connector_registry_interface::class);

        $registry->register(new connector\twilio_connector(
            account_sid: $this->config('twilio_account_sid'),
            auth_token:  $this->config('twilio_auth_token'),
            from_number: $this->config('twilio_from_number'),
        ));
    }
}

O registry e obtido do container DI. O register() e chamado uma vez por tipo.


Consultar connectors

use local_middag\facade\connector_registry;

// Obter um connector especifico.
$twilio = connector_registry::get('twilio');

if ($twilio !== null && $twilio->health_check()) {
    // Connector disponivel e saudavel.
}

// Listar todos os connectors de uma extension.
$connectors = connector_registry::for_extension('notifications');

// Listar todos os connectors registrados.
$all = connector_registry::all();

Patterns

Credenciais via settings

Armazene credenciais nas settings tipadas do MIDDAG, nunca no codigo. Use get_credential_fields() para declarar quais campos o admin precisa preencher na UI de configuracao:

public function get_credential_fields(): array
{
    return [
        ['key' => 'api_key',    'label' => 'API Key',    'type' => 'password'],
        ['key' => 'webhook_url', 'label' => 'Webhook URL', 'type' => 'url'],
    ];
}

Health check com timeout

Sempre proteja o health check contra timeouts e excecoes. O metodo deve retornar false em caso de falha, nunca lancar excecao:

public function health_check(): bool
{
    try {
        $response = $this->http->get($this->base_url . '/health', [
            'timeout' => 5,
        ]);
        return $response->is_ok();
    } catch (\Throwable) {
        return false;
    }
}

Graceful degradation

Verifique disponibilidade antes de usar. Se o servico externo estiver fora, a extension deve degradar sem derrubar o sistema:

$connector = connector_registry::get('bigquery');

if ($connector === null || !$connector->health_check()) {
    // Servico indisponivel -- fallback ou skip.
    return;
}

// Prosseguir com a integracao.

Um tipo por servico

Cada servico externo distinto deve ter seu proprio connector type. Nao misture credenciais ou endpoints de servicos diferentes no mesmo connector.


Anti-patterns

Credenciais hardcoded

// ERRADO: credenciais no codigo.
public function __construct()
{
    $this->api_key = 'sk-1234567890abcdef';
}

Credenciais devem vir de settings tipadas, injetadas via construtor.

Health check ausente

// ERRADO: retornar true sem verificar.
public function health_check(): bool
{
    return true;
}

O health check deve testar conectividade real. Um return true incondicional mascara falhas e inutiliza o monitoramento.

Health check que lanca excecao

// ERRADO: excecao escapa do health check.
public function health_check(): bool
{
    $response = $this->http->get('/ping'); // pode lancar
    return $response->is_ok();
}

Sempre envolva em try/catch. O contrato exige retorno bool.

Connector generico multi-servico

// ERRADO: um connector para multiplos servicos.
public function get_type(): string
{
    return 'payment'; // Qual? Stripe? PayPal? PagSeguro?
}

Cada servico externo e um tipo distinto: 'stripe', 'paypal', 'pagseguro'.


Referencias