Skip to content

JustSteveKing/relay

Repository files navigation

Relay

Build Status License PHP Version

Relay is a zero-bloat, fiber-native transport layer designed specifically for PHP 8.5+. It treats HTTP requests as immutable Signals flowing through a Conduit, leveraging the power of native Fibers and the Pipe Operator to deliver non-blocking I/O with a functional API.

🧠 Philosophy

  • Zero Bloat: No external dependencies. Relay relies solely on ext-curl.
  • Fiber Native: Built from the ground up for asynchronous concurrency using PHP's native Fiber and curl_multi integration.
  • Functional First: Designed for the Pipe Operator (|>), promoting immutable state and declarative request flows.
  • Type Safe: Strict typing using native Enums (Method, Status) and type aliases.

πŸ“‹ Requirements

  • PHP: 8.5 or higher
  • Extensions:
    • ext-curl
    • ext-mbstring

πŸš€ Installation

Install Relay via Composer:

composer require juststeveking/relay

πŸ— Architecture

Relay uses a unique architectural metaphor to describe its components:

  • Signal: The atomic unit of communication. It is an Interface implemented by Success | Failure. You never throw exceptions for HTTP results; you handle the Signal.
  • Conduit: The pipeline through which a Request transforms into a Signal, typically constructed using the Pipe Operator (|>).
  • Transceiver: The component responsible for converting a Request into a Signal by performing the actual network I/O.
  • WarpCore (Scheduler): The underlying event loop. It manages curl_multi handles and suspends/resumes Fibers to ensure the main thread never blocks.

πŸ“– Usage

1. The WarpCore (Scheduler)

Relay requires an active event loop to manage Fibers. Wrap your application entry point in the Scheduler::run method.

use JustSteveKing\Relay\Http\Scheduler;

Scheduler::run(function () {
    // ...
});

2. The Client (Recommended)

The Client provides a familiar API for managing base URLs, default headers, and middleware stacks.

use JustSteveKing\Relay\Client;
use JustSteveKing\Relay\Http\Middleware\Retry;
use JustSteveKing\Relay\Http\Transceiver;

$client = new Client(
    baseUrl: 'https://api.starfleet.org',
    defaultHeaders: ['Accept' => 'application/json'],
    defaultOptions: ['timeout' => 5], // Seconds
    middleware: [
        fn($next) => Retry::wrap($next, attempts: 3)
    ]
);

$signal = $client->get('/sector/001');

3. Functional Requests (Advanced)

Requests are immutable. Use the Pipe Operator to send them through the Transceiver.

use JustSteveKing\Relay\Http\Request;
use JustSteveKing\Relay\Http\Transceiver;
use JustSteveKing\Relay\Http\Success;
use JustSteveKing\Relay\Http\Failure;
use JustSteveKing\Relay\Http\Status;

$signal = new Request(
    uri: 'https://api.starfleet.org/sector/001', 
    options: ['allow_redirects' => true]
)
    |> Transceiver::send(...);

match(true) {
    $signal instanceof Success => printf("Status: %s", $signal->status->name),
    $signal instanceof Failure => printf("Alert! %s", $signal->reason),
};

4. Authentication

Relay provides a functional Auth helper to decorate requests with headers. These are stateless and return a modified clone of the Request.

use JustSteveKing\Relay\Http\Auth;
use JustSteveKing\Relay\Http\Method;

$request = new Request('https://secure.starfleet.org/files', Method::POST);

$signal = $request
    |> Auth::bearer('spf-12345-token')
    |> Transceiver::send(...);

Supported methods:

  • Auth::bearer(string $token)
  • Auth::basic(string $user, string $pass)
  • Auth::apiKey(string $key, string $header = 'X-API-Key')

5. Concurrent Requests

Execute multiple requests in parallel using the Concurrent, Pool, or Race helpers.

Basic Concurrency:

use JustSteveKing\Relay\Http\Concurrent;

$results = Concurrent::run([
    'profile' => fn() => Transceiver::send($profileReq),
    'feed'    => fn() => Transceiver::send($feedReq),
]);

Concurrency Limiting (Pool):

use JustSteveKing\Relay\Http\Pool;

// Process 100 requests, but only 5 at a time
$results = Pool::work($largeListOfTasks, concurrency: 5);

First to Finish (Race):

use JustSteveKing\Relay\Http\Race;

// Returns the first result, discards the rest
$winner = Race::any([
    fn() => Transceiver::send($primary),
    fn() => Transceiver::send($backup),
]);

6. Custom Actions

Encapsulate logic into Action classes. This promotes reusability and clean architecture.

namespace App\Actions;

use JustSteveKing\Relay\Http\Method;
use JustSteveKing\Relay\Http\Request;
use JustSteveKing\Relay\Http\Transceiver;
use JustSteveKing\Relay\Contracts\Signal;

class Starbase
{
    public static function hail(string $baseId): Signal
    {
        // "Immutable mutation" using PHP 8.5 features or the with() helper
        return new Request(uri: "https://api.starfleet.org/v1/starbase/{$baseId}")
            |> (fn($req) => $req->with(['method' => Method::GET]))
            |> Transceiver::send(...);
    }
}

πŸ“š Documentation

πŸ’‘ Examples

Check the examples/ directory for ready-to-run scripts:

πŸ›  Development

Relay is built with high quality standards.

Running Tests

composer test

Static Analysis

composer analyse

Code Style (Linting)

composer lint
# or to fix automatically
composer fix

πŸ“„ License

Relay is open-sourced software licensed under the MIT license.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages