vasatiani/laravel-athena

Laravel Athena query builder integration with Eloquent support and Redis-safe concurrency.

dev-main 2025-04-30 14:50 UTC

This package is auto-updated.

Last update: 2025-05-30 14:59:13 UTC


README

A modern, clean, and scalable integration of AWS Athena with Laravel's Query Builder and Eloquent ORM.
Built with full support for Laravel 10–12, Redis-based concurrency limits, Octane/Swoole compatibility, and Athena-specific query and schema grammar.

πŸš€ Features

  • βœ… Eloquent & Query Builder support
  • βœ… Safe concurrency control (Athena allows max 20 concurrent queries)
  • βœ… S3 query result management
  • βœ… Redis lock support (Octane/Swoole-friendly)
  • βœ… Schema-aware DDL generation (CREATE TABLE)
  • βœ… Custom grammar for BETWEENLIMIT, Athena-safe LIMIT/OFFSET
  • βœ… Fully configurable via config/athena.php

πŸ“¦ Installation

composer require vasatiani/laravel-athena

Then publish the config file:

php artisan vendor:publish --tag=config

πŸ›  Configuration

Located in config/athena.php

return [
    'credentials' => [
        'key'    => env('AWS_KEY', ''),
        'secret' => env('AWS_SECRET', ''),
    ],
    'region'        => env('AWS_REGION', 'eu-central-1'),
    'version'       => 'latest',
    'database'      => env('ATHENA_DB', ''),
    'prefix'        => env('ATHENA_TABLE_PREFIX', ''),
    'bucket'        => env('S3_BUCKET', ''),
    'outputfolder'  => env('ATHENA_OUTPUT_FOLDER', 'athena-output'),

    's3output'      => 's3://' . env('S3_BUCKET', '') . '/' . env('ATHENA_OUTPUT_FOLDER', 'athena-output'),

    // Concurrency control
    'lock_key'      => env('ATHENA_LOCK_KEY', 'athena:query:concurrency'),
    'lock_timeout'  => env('ATHENA_LOCK_TIMEOUT', 10),
    'lock_wait'     => env('ATHENA_LOCK_WAIT', 5),

    // Schema creation options
    'stored_as' => 'PARQUET',
    'table_properties' => [
        'has_encrypted_data' => 'false',
        'classification'     => 'json',
    ],
];

Make sure your .env contains:

AWS_KEY=your-key
AWS_SECRET=your-secret
AWS_REGION=eu-central-1
S3_BUCKET=your-bucket
ATHENA_DB=your_database
ATHENA_OUTPUT_FOLDER=athena-output

🧩 Usage

πŸ— Defining a Model

namespace App\Models;

use Vasatiani\Athena\Model;

class AthenaEvent extends Model
{
    protected $table = 'events';
}

πŸ“‹ Running Queries

use App\Models\AthenaEvent;

$events = AthenaEvent::where('event_type', 'login')->get();

$events = AthenaEvent::query()
    ->whereDateBetween('created_at', '2024-01-01', '2024-01-31')
    ->get();

$events = AthenaEvent::whereRegex('event_name', '^checkout_.*')->get();

πŸ” Automatic Query Caching

Queries are hashed and stored in the athena_query_hashes table.

If the table is missing, the system will fallback gracefully.

Migration:

Schema::create('athena_query_hashes', function (Blueprint $table) {
    $table->string('query_hash')->primary();
    $table->string('aws_return_id');
    $table->timestamps();
});

πŸ’₯ Custom Query Builder Helpers

AthenaEvent::whereNotEmpty('email')->get();
AthenaEvent::selectIfEmpty(['id', 'name'])->get();
AthenaEvent::whereJsonHasKey('payload', 'device_id')->get();

🧱 Schema Support (Optional)

Schema::connection('athena')->create('events', function (Blueprint $table) {
    $table->string('event_type');
    $table->timestamp('created_at');
});

This generates:

CREATE EXTERNAL TABLE events (
  event_type string,
  created_at timestamp
)
STORED AS PARQUET
LOCATION 's3://your-bucket/athena-output'
TBLPROPERTIES ('has_encrypted_data'='false','classification'='json')

⚠️ Athena LIMIT & OFFSET Handling

Internally converted to ROW_NUMBER() queries via special syntax BETWEENLIMIT.

βœ… Redis Lock Integration

Uses Laravel's Cache::lock() to prevent exceeding Athena’s concurrency limits.

πŸ§ͺ Testing

DB::connection('athena')->select("SELECT count(*) as total FROM users");

πŸ“˜ License

MIT Β© Vakho Asatiani