Skip to content

Commit

Permalink
Provide better experience on installing a new Laravel project with em…
Browse files Browse the repository at this point in the history
…bedded replica
  • Loading branch information
richan-fongdasen committed Apr 16, 2024
1 parent 06c2b44 commit 6743b68
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 48 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"keywords": [
"Richan Fongdasen",
"turso",
"libsql",
"laravel",
"turso-laravel"
],
Expand Down
2 changes: 1 addition & 1 deletion config/turso-laravel.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// config for RichanFongdasen/TursoLaravel
return [
'sync' => [
'sync_command' => [
'script_filename' => 'turso-sync.mjs',
'script_path' => realpath(__DIR__ . '/..'),
'timeout' => 60,
Expand Down
2 changes: 2 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
parameters:
treatPhpDocTypesAsCertain: false
ignoreErrors:
- '#Variable method call on RichanFongdasen\\Turso\\TursoHttpClient.#'
6 changes: 3 additions & 3 deletions src/Commands/TursoSyncCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ protected function compileRunProcess(): string
{
return sprintf(
'node %s "%s" "%s" "%s"',
config('turso-laravel.sync.script_filename'),
config('turso-laravel.sync_command.script_filename'),
config('database.connections.turso.db_url'),
config('database.connections.turso.access_token'),
config('database.connections.turso.db_replica'),
Expand All @@ -26,10 +26,10 @@ protected function compileRunProcess(): string

public function handle(): int
{
$timeout = (int) config('turso-laravel.sync.timeout');
$timeout = (int) config('turso-laravel.sync_command.timeout');

$result = Process::timeout($timeout)
->path(config('turso-laravel.sync.script_path') ?? base_path())
->path(config('turso-laravel.sync_command.script_path') ?? base_path())
->run($this->compileRunProcess());

if ($result->failed()) {
Expand Down
79 changes: 42 additions & 37 deletions src/Database/TursoConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,49 @@

use Illuminate\Database\SQLiteConnection;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;

class TursoConnection extends SQLiteConnection
{
protected bool $hasUpdated = false;

protected static array $updatingStatements = [
'alter',
'create',
'delete',
'drop',
'insert',
'truncate',
'update',
];

public function __construct(TursoPDO $pdo, string $database = ':memory:', string $tablePrefix = '', array $config = [])
{
parent::__construct($pdo, $database, $tablePrefix, $config);
}

/**
* Run an SQL statement and get the number of rows affected.
*
* @param string $query
* @param array $bindings
*
* @return int
*/
public function affectingStatement($query, $bindings = [])
{
if ($this->queryIsUpdatingRemoteDB($query)) {
$this->hasUpdated = true;
}

return parent::affectingStatement($query, $bindings);
}

protected function queryIsUpdatingRemoteDB(string $query): bool
{
return Str::startsWith(trim(strtolower($query)), self::$updatingStatements);
}

/**
* Get the default query grammar instance.
*/
Expand Down Expand Up @@ -70,53 +103,25 @@ protected function getDefaultPostProcessor(): TursoQueryProcessor
return new TursoQueryProcessor();
}

/**
* Run an insert statement against the database.
*
* @param string $query
* @param array $bindings
*
* @return bool
*/
public function insert($query, $bindings = [])
{
$this->hasUpdated = true;

return parent::insert($query, $bindings);
}

/**
* Run an update statement against the database.
*
* @param string $query
* @param array $bindings
*
* @return int
*/
public function update($query, $bindings = [])
public function hasUpdated(): bool
{
$this->hasUpdated = true;

return parent::update($query, $bindings);
return $this->hasUpdated;
}

/**
* Run a delete statement against the database.
* Execute an SQL statement and return the boolean result.
*
* @param string $query
* @param array $bindings
*
* @return int
* @return bool
*/
public function delete($query, $bindings = [])
public function statement($query, $bindings = [])
{
$this->hasUpdated = true;

return parent::delete($query, $bindings);
}
if ($this->queryIsUpdatingRemoteDB($query)) {
$this->hasUpdated = true;
}

public function hasUpdated(): bool
{
return $this->hasUpdated;
return parent::statement($query, $bindings);
}
}
1 change: 1 addition & 0 deletions src/Facades/Turso.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
/**
* @see \RichanFongdasen\Turso\TursoHttpClient
*
* @mixin \RichanFongdasen\Turso\TursoManager
* @mixin \RichanFongdasen\Turso\TursoHttpClient
*/
class Turso extends Facade
Expand Down
2 changes: 1 addition & 1 deletion src/TursoHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public function request(): PendingRequest
public function resetClientState(): void
{
$this->baton = null;
$this->baseUrl = data_get($this->config, 'db_url');
$this->baseUrl = (string) data_get($this->config, 'db_url', '');
$this->isOpen = false;
}
}
39 changes: 38 additions & 1 deletion src/TursoLaravelServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,53 @@

namespace RichanFongdasen\Turso;

use Illuminate\Console\Events\CommandFinished;
use Illuminate\Console\Events\CommandStarting;
use Illuminate\Database\Connection;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Facades\Event;
use PDO;
use RichanFongdasen\Turso\Commands\TursoSyncCommand;
use RichanFongdasen\Turso\Database\TursoConnection;
use RichanFongdasen\Turso\Database\TursoConnector;
use RichanFongdasen\Turso\Facades\Turso;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;

class TursoLaravelServiceProvider extends PackageServiceProvider
{
public function boot(): void
{
parent::boot();

if (config('database.default') !== 'turso') {
return;
}

Event::listen(function (CommandStarting $event) {
if (! app()->bound('running-artisan-command')) {
app()->instance('running-artisan-command', data_get($event, 'command'));
}

Turso::disableReadReplica();
});

Event::listen(function (CommandFinished $event) {
if (data_get($event, 'command') === 'turso:sync') {
return;
}

if (
app()->bound(TursoConnection::class) &&
app(TursoConnection::class)->hasUpdated() &&
(app('running-artisan-command') === data_get($event, 'command'))
) {
Turso::sync();
Turso::enableReadReplica();
}
});
}

public function configurePackage(Package $package): void
{
/*
Expand All @@ -37,7 +73,7 @@ public function register(): void
parent::register();

$this->app->scoped(TursoManager::class, function () {
return new TursoManager(config('database.connections.turso'));
return new TursoManager(config('database.connections.turso', []));
});

$this->app->extend(DatabaseManager::class, function (DatabaseManager $manager) {
Expand All @@ -46,6 +82,7 @@ public function register(): void
$pdo = $connector->connect($config);

$connection = new TursoConnection($pdo, $database ?? 'turso', $prefix, $config);
app()->instance(TursoConnection::class, $connection);

$replicaPath = (string) data_get($config, 'db_replica');

Expand Down
9 changes: 4 additions & 5 deletions src/TursoManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,12 @@ public function sync(): void
}
}

public function __call(string $methodName, array $arguments = []): mixed
public function __call(string $method, array $arguments = []): mixed
{
if (! method_exists($this->client, $methodName)) {
throw new BadMethodCallException('Call to undefined method ' . static::class . '::' . $methodName . '()');
if (! method_exists($this->client, $method)) {
throw new BadMethodCallException('Call to undefined method ' . static::class . '::' . $method . '()');
}

// @phpstan-ignore-next-line
return call_user_func_array([$this->client, $methodName], $arguments);
return $this->client->$method(...$arguments);
}
}
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@ public function getEnvironmentSetUp($app)
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
]);
config()->set('database.default', 'turso');
config()->set('queue.default', 'sync');
}
}
4 changes: 4 additions & 0 deletions tests/Unit/TursoHttpClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
];

Turso::enableQueryLog();
Turso::freshRequest();

Turso::query($query['statement'], $query['bindings']);

Expand All @@ -39,6 +40,8 @@
'*' => Http::response(['message' => 'Internal Server Error'], 500),
]);

Turso::freshRequest();

Turso::query('SELECT * FROM "users"');
})->throws(RequestException::class)->group('TursoClient', 'UnitTest');

Expand Down Expand Up @@ -73,6 +76,7 @@
),
]);

Turso::freshRequest();
Turso::query('SELECT * FROM "users"');

expect(Turso::getBaseUrl())->toBe('http://base-url-example.turso.io');
Expand Down

0 comments on commit 6743b68

Please sign in to comment.