genesisdb/client-sdk

There is no license information available for the latest version (1.0.3) of this package.

PHP SDK for Genesis DB

Installs: 3

Dependents: 1

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/genesisdb/client-sdk

1.0.3 2025-10-07 15:49 UTC

This package is not auto-updated.

Last update: 2025-10-12 18:15:22 UTC


README

This is the official PHP SDK for Genesis DB, an awesome and production ready event store database system for building event-driven apps.

Genesis DB Advantages

  • Incredibly fast when reading, fast when writing 🚀
  • Easy backup creation and recovery
  • CloudEvents compatible
  • GDPR-ready
  • Easily accessible via the HTTP interface
  • Auditable. Guarantee database consistency
  • Logging and metrics for Prometheus
  • SQL like query language called Genesis DB Query Language (GDBQL)

Installation

Just run:

composer require genesisdb/client-sdk

Usage

use GenesisDB\GenesisDB\Client;

final class AcmeClass
{

    /**
     * @return Client
     */
    private function genesisDbClient(): Client
    {
        return new Client($this->apiUrl, $this->apiVersion, $this->authToken);
    }

    /**
     * @param string $subject
     * @param string|null $lowerBound
     * @param bool|null $includeLowerBoundEvent
     * @param string|null $latestByEventType
     * @return array
     */
    public function streamEvents(
        string $subject,
        ?string $lowerBound = null,
        ?bool $includeLowerBoundEvent = null,
        ?string $latestByEventType = null
    ): array
    {
        return $this->genesisDbClient()->streamEvents(
            $subject,
            $lowerBound,
            $includeLowerBoundEvent,
            $latestByEventType
        );
    }

     /**
     * @param string $subject
     * @param string|null $lowerBound
     * @param bool|null $includeLowerBoundEvent
     * @param string|null $latestByEventType
     * @return \Generator
     */
    public function observeEvents(
        string $subject,
        ?string $lowerBound = null,
        ?bool $includeLowerBoundEvent = null,
        ?string $latestByEventType = null
    ): \Generator
    {
        return $this->genesisDbClient()->observeEvents(
            $subject,
            $lowerBound,
            $includeLowerBoundEvent,
            $latestByEventType
        );
    }

    /**
     * @param array $events Array of events with subject, type, and data
     * @param array|null $preconditions Optional preconditions for the commit
     * @return void
     */
    public function commitEvents(array $events, ?array $preconditions = null): void
    {
        $this->genesisDbClient()->commitEvents($events, $preconditions);
    }

    /**
     * @param string $subject
     * @return void
     */
    public function eraseData(string $subject): void
    {
        $this->genesisDbClient()->eraseData($subject);
    }

    /**
     * @param string $query
     * @return array
     */
    public function queryEvents(string $query): array
    {
        return $this->genesisDbClient()->q($query);
    }

    /**
     * @return string
     */
    public function audit(): string
    {
        return $this->genesisDbClient()->audit();
    }

    /**
     * @return string
     */
    public function ping(): string
    {
        return $this->genesisDbClient()->ping();
    }

}

Examples

Basic Event Streaming

// Stream all events for a subject
$events = $client->streamEvents('/customer');

foreach ($events as $event) {
    echo "Event Type: " . $event['type'] . ", Data: " . json_encode($event['data']) . "\n";
}

Stream Events from Lower Bound

// Stream events from a specific lower bound
$events = $client->streamEvents(
    '/',
    '2d6d4141-6107-4fb2-905f-445730f4f2a9',
    true
);

foreach ($events as $event) {
    echo "Event Type: " . $event['type'] . ", Data: " . json_encode($event['data']) . "\n";
}

Stream Latest Events by Event Type

// Get latest events by event type
$latestEvents = $client->streamEvents(
    '/',
    null,
    null,
    'io.genesisdb.app.customer-updated'
);

foreach ($latestEvents as $event) {
    echo "Latest Event: " . $event['type'] . "\n";
}

Observe Events in Real-Time

// Observe events as they occur
foreach ($client->observeEvents('/customer') as $event) {
    echo "Received event: " . $event->getType() . "\n";
    echo "Data: " . json_encode($event->getData()) . "\n";
}

Observe Events from Lower Bound (Message Queue)

// Observe events from a specific point
foreach ($client->observeEvents('/customer', '2d6d4141-6107-4fb2-905f-445730f4f2a9', true) as $event) {
    echo "Received event: " . $event->getType() . "\n";
}

Observe Latest Events by Event Type (Message Queue)

// Observe only latest events of a specific type
foreach ($client->observeEvents('/customer', null, null, 'io.genesisdb.app.customer-updated') as $event) {
    echo "Latest event: " . $event->getType() . "\n";
}

Committing Events

// Commit events without preconditions
$events = [
    [
        'source' => 'io.genesisdb.app',
        'subject' => '/customer',
        'type' => 'io.genesisdb.app.customer-added',
        'data' => [
            'firstName' => 'Bruce',
            'lastName' => 'Wayne',
            'emailAddress' => 'bruce.wayne@enterprise.wayne'
        ]
    ],
    [
        'source' => 'io.genesisdb.app',
        'subject' => '/customer',
        'type' => 'io.genesisdb.app.customer-added',
        'data' => [
            'firstName' => 'Alfred',
            'lastName' => 'Pennyworth',
            'emailAddress' => 'alfred.pennyworth@enterprise.wayne'
        ]
    ],
    [
        'source' => 'io.genesisdb.store',
        'subject' => '/article',
        'type' => 'io.genesisdb.store.article-added',
        'data' => [
            'name' => 'Tumbler',
            'color' => 'black',
            'price' => 2990000.00
        ]
    ],
    [
        'source' => 'io.genesisdb.app',
        'subject' => '/customer/fed2902d-0135-460d-8605-263a06308448',
        'type' => 'io.genesisdb.app.customer-personaldata-changed',
        'data' => [
            'firstName' => 'Angus',
            'lastName' => 'MacGyver',
            'emailAddress' => 'angus.macgyer@phoenix.foundation'
        ]
    ]
];

$client->commitEvents($events);

Preconditions

Preconditions allow you to enforce certain checks on the server before committing events. Genesis DB supports multiple precondition types:

isSubjectNew

Ensures that a subject is new (has no existing events):

$events = [
    [
        'source' => 'io.genesisdb.app',
        'subject' => '/user/456',
        'type' => 'io.genesisdb.app.user-created',
        'data' => [
            'firstName' => 'John',
            'lastName' => 'Doe',
            'email' => 'john.doe@example.com'
        ]
    ]
];

$preconditions = [
    [
        'type' => 'isSubjectNew',
        'payload' => [
            'subject' => '/user/456'
        ]
    ]
];

$client->commitEvents($events, $preconditions);

isQueryResultTrue

Evaluates a query and ensures the result is truthy. Supports the full GDBQL feature set including complex WHERE clauses, aggregations, and calculated fields.

Basic uniqueness check:

$events = [
    [
        'source' => 'io.genesisdb.app',
        'subject' => '/user/456',
        'type' => 'io.genesisdb.app.user-created',
        'data' => [
            'firstName' => 'John',
            'lastName' => 'Doe',
            'email' => 'john.doe@example.com'
        ]
    ]
];

$preconditions = [
    [
        'type' => 'isQueryResultTrue',
        'payload' => [
            'query' => "STREAM e FROM events WHERE e.data.email == 'john.doe@example.com' MAP COUNT() == 0"
        ]
    ]
];

$client->commitEvents($events, $preconditions);

Business rule enforcement (transaction limits):

$events = [
    [
        'source' => 'io.genesisdb.banking',
        'subject' => '/user/123/transactions',
        'type' => 'io.genesisdb.banking.transaction-processed',
        'data' => [
            'amount' => 500.00,
            'currency' => 'EUR'
        ]
    ]
];

$preconditions = [
    [
        'type' => 'isQueryResultTrue',
        'payload' => [
            'query' => "STREAM e FROM events WHERE e.subject UNDER '/user/123' AND e.type == 'transaction-processed' AND e.time >= '2024-01-01T00:00:00Z' MAP SUM(e.data.amount) + 500 <= 10000"
        ]
    ]
];

$client->commitEvents($events, $preconditions);

Complex validation with aggregations:

$events = [
    [
        'source' => 'io.genesisdb.events',
        'subject' => '/conference/2024/registrations',
        'type' => 'io.genesisdb.events.registration-created',
        'data' => [
            'attendeeId' => 'att-789',
            'ticketType' => 'premium'
        ]
    ]
];

$preconditions = [
    [
        'type' => 'isQueryResultTrue',
        'payload' => [
            'query' => "STREAM e FROM events WHERE e.subject UNDER '/conference/2024/registrations' AND e.type == 'registration-created' GROUP BY e.data.ticketType HAVING e.data.ticketType == 'premium' MAP COUNT() < 50"
        ]
    ]
];

$client->commitEvents($events, $preconditions);

Supported GDBQL Features in Preconditions:

  • WHERE conditions with AND/OR/IN/BETWEEN operators
  • Hierarchical subject queries (UNDER, DESCENDANTS)
  • Aggregation functions (COUNT, SUM, AVG, MIN, MAX)
  • GROUP BY with HAVING clauses
  • ORDER BY and LIMIT clauses
  • Calculated fields and expressions
  • Nested field access (e.data.address.city)
  • String concatenation and arithmetic operations

If a precondition fails, the commit returns HTTP 412 (Precondition Failed) with details about which condition failed.

GDPR Compliance

Store Data as Reference

$events = [
    [
        'source' => 'io.genesisdb.app',
        'subject' => '/user/456',
        'type' => 'io.genesisdb.app.user-created',
        'data' => [
            'firstName' => 'John',
            'lastName' => 'Doe',
            'email' => 'john.doe@example.com'
        ],
        'options' => [
            'storeDataAsReference' => true
        ]
    ]
];

$client->commitEvents($events);

Delete Referenced Data

// Erase all data for a specific subject (GDPR compliance)
$client->eraseData('/user/456');

Querying Events

// Query using GDBQL
$query = 'STREAM e FROM events WHERE e.type == "io.genesisdb.app.customer-added" ORDER BY e.time DESC LIMIT 20 MAP { subject: e.subject, firstName: e.data.firstName }';

$results = $client->q($query);

foreach ($results as $result) {
    echo "Result: " . json_encode($result) . "\n";
}

Health Checks

// Check API status
$pingResponse = $client->ping();
echo "Ping response: " . $pingResponse . "\n";

// Run audit to check event consistency
$auditResponse = $client->audit();
echo "Audit response: " . $auditResponse . "\n";

License

MIT

Author