Compare commits

..

3 Commits

Author SHA1 Message Date
lexx ab1517cc8f tabs and date in modal fix 2024-08-30 13:38:34 +03:00
lexx 9f724a3243 better report 2024-08-27 17:59:12 +03:00
lexx ae65ca47f6 commands and logs to the database 2024-08-27 17:42:06 +03:00
24 changed files with 316 additions and 158 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"main.js": { "main.js": {
"file": "assets/main-1FLcNLEV.js", "file": "assets/main-D9joEh0I.js",
"name": "main", "name": "main",
"src": "main.js", "src": "main.js",
"isEntry": true, "isEntry": true,
"css": [ "css": [
"assets/main-U24QISX_.css" "assets/main-BnJW41Dx.css"
] ]
} }
} }
+14 -1
View File
@@ -8,6 +8,7 @@
$: date = ""; $: date = "";
$: logs = ""; $: logs = "";
let anchorEl;
let inProgress = false; let inProgress = false;
function connect() { function connect() {
@@ -18,6 +19,7 @@
const data = JSON.parse(event.data); const data = JSON.parse(event.data);
date = data.date; date = data.date;
logs = data.logs; logs = data.logs;
anchorEl.scrollIntoView()
} }
eventSource.onerror = (e) => { eventSource.onerror = (e) => {
console.log(e) console.log(e)
@@ -65,6 +67,17 @@
</div> </div>
<pre>{logs}</pre> <pre class="logs">{logs}
<div bind:this={anchorEl}>&nbsp;</div>
</pre>
</div> </div>
</div> </div>
<style>
.logs{
max-height: 70vh;
overflow: scroll;
background: var(--p90);
color: var(--p10);
padding: 10px;
}
</style>
@@ -9,13 +9,17 @@
export let value; export let value;
export let isCreateMode; export let isCreateMode;
export let validationErrors; export let validationErrors;
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
$: errorMessage = getErrorMessage(validationErrors, field.name); $: errorMessage = getErrorMessage(validationErrors, field.name);
export let id; export let id;
let wrapperDiv;
let pickerInput; let pickerInput;
let pickerInstance; let pickerInstance;
let flatpickrOptions = { let flatpickrOptions = {
appendTo: wrapperDiv,
static: true,
allowInput: true, allowInput: true,
altInput: true, altInput: true,
altFormat: "Y-m-d H:i:S", altFormat: "Y-m-d H:i:S",
@@ -40,7 +44,7 @@
}); });
</script> </script>
<div class="mb-0"> <div class="mb-0" bind:this={wrapperDiv}>
<input <input
type="text" type="text"
@@ -67,7 +67,7 @@
class=" button" class=" button"
on:click={(e) => on:click={(e) =>
createInlineReference(e, schema.name)} createInlineReference(e, schema.name)}
>{schema.name} >{schema.label}
</button> </button>
{/each} {/each}
@@ -78,7 +78,7 @@
<button <button
class="button" class="button"
on:click={(e) => openBrowseModal(e, schema.name)} on:click={(e) => openBrowseModal(e, schema.name)}
>{schema.name} >{schema.label}
</button> </button>
{/each} {/each}
+1
View File
@@ -3,6 +3,7 @@
margin: 20px 0 20px; margin: 20px 0 20px;
display: flex; display: flex;
gap: 4px; gap: 4px;
flex-wrap: wrap;
.tab{ .tab{
list-style: none; list-style: none;
+3
View File
@@ -105,3 +105,6 @@ a {
position: relative; position: relative;
} }
.flatpickr-wrapper {
display: block!important;
}
+1 -1
View File
@@ -31,7 +31,7 @@ final class ChannelService
$schemasCollection = (new Collection($schemasArray["schemas"] ?? []))->map([$schemaService, 'fromArray']); $schemasCollection = (new Collection($schemasArray["schemas"] ?? []))->map([$schemaService, 'fromArray']);
$userCommands = []; $userCommands = [];
foreach (config("lucent.commands") as $signature => $desc) { foreach (config("lucent.commands") ?? [] as $signature => $desc) {
$userCommands[] = new UserCommand($desc, $signature); $userCommands[] = new UserCommand($desc, $signature);
} }
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace Lucent\Command;
use Illuminate\Support\Facades\DB;
use Lucent\Command\Data\CommandLogItem;
class CommandRepo
{
public function findBySignature($signature): ?CommandLogItem
{
$row = DB::table("command_logs")->where("signature", $signature)->first();
if (empty($row)) {
return null;
}
return CommandLogItem::fromDB($row);
}
public function upsertCommand(CommandLogItem $commandLogItem): void
{
$foundCommandLogItem = $this->findBySignature($commandLogItem->signature);
if (empty($foundCommandLogItem)) {
DB::table("command_logs")->insert(toArray($commandLogItem));
return;
}
DB::table("command_logs")->where("signature", $commandLogItem->signature)->update(toArray($commandLogItem));
}
public function appendToLogs(string $signature, string $line): void
{
$res = DB::update(
'update command_logs set logs = logs || ? where signature = ?',
[$line, $signature]
);
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace Lucent\Command;
use Lucent\Command\Data\CommandLogItem;
use Lucent\Id\Id;
use Lucent\LucentException;
use Symfony\Component\Process\PhpExecutableFinder;
class CommandService
{
public function __construct(
private CommandRepo $commandRepo,
)
{
}
public function run(string $signature): CommandLogItem
{
$commandLogItem = $this->commandRepo->findBySignature($signature);
if (empty($commandLogItem)) {
$commandLogItem = new CommandLogItem(
id: Id::new(),
signature: $signature,
pid: null,
logs: ""
);
} elseif ($this->commandIsRunning($commandLogItem->pid)) {
throw new LucentException('Command is already running');
}
$commandLogItem->pid = $this->runCommand($signature);
$commandLogItem->logs = "";
$this->commandRepo->upsertCommand($commandLogItem);
return $commandLogItem;
}
public function logWriter(string $signature): callable
{
return function (string $line) use($signature) {
$this->commandRepo->appendToLogs($signature, $line.PHP_EOL);
};
}
private function runCommand(string $signature): int
{
$phpBinaryFinder = new PhpExecutableFinder();
$phpBinaryPath = $phpBinaryFinder->find();
$pid = (int)shell_exec("cd " . base_path() . " && $phpBinaryPath artisan {$signature} > /dev/null 2>&1 & echo $!");
return $pid;
}
public function commandIsRunning(int $pid): bool
{
return file_exists("/proc/$pid");
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Lucent\Command\Data;
use stdClass;
class CommandLogItem
{
public function __construct(
public string $id,
public string $signature,
public ?int $pid,
public string $logs,
)
{
}
public static function fromDB(stdClass $data): self
{
return new self(
id: $data->id,
signature: $data->signature,
pid: $data->pid,
logs: $data->logs,
);
}
}
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration { return new class extends Migration {
protected $connection = 'lucentDb'; protected $connection = 'lucentdb';
/** /**
* Run the migrations. * Run the migrations.
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class extends Migration
{ {
protected $connection = 'lucentDb'; protected $connection = 'lucentdb';
/** /**
* Run the migrations. * Run the migrations.
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration { return new class extends Migration {
protected $connection = 'lucentDb'; protected $connection = 'lucentdb';
/** /**
* Run the migrations. * Run the migrations.
* *
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration { return new class extends Migration {
protected $connection = 'lucentDb'; protected $connection = 'lucentdb';
/** /**
* Run the migrations. * Run the migrations.
* *
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration { return new class extends Migration {
protected $connection = 'lucentDb'; protected $connection = 'lucentdb';
/** /**
* Run the migrations. * Run the migrations.
* *
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration { return new class extends Migration {
protected $connection = 'lucentDb'; protected $connection = 'lucentdb';
/** /**
* Run the migrations. * Run the migrations.
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
protected $connection = 'lucentdb';
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('command_logs', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('signature');
$table->integer('pid')->nullable();
$table->text('logs');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('command_logs');
}
};
+12 -37
View File
@@ -6,13 +6,17 @@ use App\Http\Controllers\Controller;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Lucent\Channel\ChannelService; use Lucent\Channel\ChannelService;
use Lucent\Command\CommandRepo;
use Lucent\Command\CommandService;
use Lucent\Svelte\Svelte; use Lucent\Svelte\Svelte;
class BuildController extends Controller class BuildController extends Controller
{ {
public function __construct( public function __construct(
public readonly Svelte $svelte, private readonly Svelte $svelte,
public readonly ChannelService $channelService, private readonly ChannelService $channelService,
private readonly CommandService $commandService,
private readonly CommandRepo $commandRepo,
) )
{ {
} }
@@ -20,19 +24,8 @@ class BuildController extends Controller
public function build(Request $request) public function build(Request $request)
{ {
$commandSignature = $request->route("signature"); $commandSignature = $request->route("signature");
$buildLogFile = $this->getLogFile($commandSignature); $this->commandService->run($commandSignature);
$pidFile = $this->getPidFile($commandSignature);
if (file_exists($buildLogFile)) {
unlink($buildLogFile);
}
if (file_exists($pidFile)) {
unlink($pidFile);
}
exec("cd " . base_path() . " && php8.3 artisan {$commandSignature} > " . $buildLogFile . " 2>&1 & echo $!", $op);
$pid = (int)$op[0];
file_put_contents($pidFile, $pid);
return redirect($this->channelService->channel->lucentUrl . "/command-report/" . $commandSignature);
} }
public function report(Request $request): View public function report(Request $request): View
@@ -55,8 +48,10 @@ class BuildController extends Controller
$commandSignature = $request->route("signature"); $commandSignature = $request->route("signature");
return response()->stream(function () use ($commandSignature) { return response()->stream(function () use ($commandSignature) {
while (true) { while (true) {
$commandLogItem = $this->commandRepo->findBySignature($commandSignature);
$data["date"] = date("Y-m-d H:i:s"); $data["date"] = date("Y-m-d H:i:s");
$data["logs"] = file_get_contents($this->getLogFile($commandSignature)); $data["logs"] = $commandLogItem->logs ?? "";
// $lines = explode("\n",$data["logs"]); // $lines = explode("\n",$data["logs"]);
echo 'data: ' . json_encode($data); echo 'data: ' . json_encode($data);
@@ -64,19 +59,8 @@ class BuildController extends Controller
ob_flush(); ob_flush();
flush(); flush();
logger($this->commandService->commandIsRunning($commandLogItem->pid));
$pidFile = $this->getPidFile($commandSignature); if (!$this->commandService->commandIsRunning($commandLogItem->pid)) {
if (file_exists($pidFile)) {
$pid = file_get_contents($pidFile);
} else {
break;
}
if (empty($pid)) {
break;
}
if (!file_exists("/proc/$pid")) {
break; break;
} }
@@ -93,13 +77,4 @@ class BuildController extends Controller
]); ]);
} }
private function getLogFile(string $signature): string
{
return storage_path("lucent/$signature.log");
}
private function getPidFile(string $signature): string
{
return storage_path("lucent/$signature.pid.log");
}
} }
+4 -1
View File
@@ -33,8 +33,11 @@ class LucentServiceProvider extends ServiceProvider
return new ImageManager(['driver' => 'imagick']); return new ImageManager(['driver' => 'imagick']);
}); });
$this->app->bind(DatabaseGraph::class, function () { $this->app->bind(DatabaseGraph::class, function () {
return match (config("lucent.database")) { $dbConnection = config("lucent.database");
return match (config("database.connections.$dbConnection.driver")) {
"sqlite" => new SqliteDatabaseGraph(), "sqlite" => new SqliteDatabaseGraph(),
"pgsql" => new PgsqlDatabaseGraph(), "pgsql" => new PgsqlDatabaseGraph(),
}; };
+14 -14
View File
@@ -3,38 +3,37 @@
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Contracts\View\View; use Lucent\Command\CommandService;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Throwable; use Throwable;
class StaticGenerator class StaticGenerator
{ {
public function __construct( public function __construct(
public Writer $writer, public Filesystem $filesystem,
public Filesystem $filesystem public CommandService $commandService,
) )
{ {
} }
public function run(callable $callback): void public function run(string $signature, callable $callback): void
{ {
$logWriter = $this->commandService->logWriter($signature);
echo "Start ".Carbon::now()->format("Y-m-d H:i:s").PHP_EOL; $logWriter("Start " . Carbon::now()->format("Y-m-d H:i:s"));
$this->removeBuildDirectory(); $this->removeBuildDirectory();
echo "Removing previous data".PHP_EOL; $logWriter("Removing previous data");
try { try {
$callback($this->writer); $callback(new Writer($logWriter));
} catch (Throwable $th) { } catch (Throwable $th) {
echo "Finished with errors".Carbon::now()->format("Y-m-d H:i:s")." ".$th->getMessage().PHP_EOL; $logWriter("Finished with errors" . Carbon::now()->format("Y-m-d H:i:s") . " " . $th->getMessage());
} }
$this->copyBuildDirectory(); $this->copyBuildDirectory();
echo "Finished ".Carbon::now()->format("Y-m-d H:i:s").PHP_EOL; $logWriter("Finished " . Carbon::now()->format("Y-m-d H:i:s"));
} }
private function removeBuildDirectory() :void{ private function removeBuildDirectory(): void
{
if (!file_exists(storage_path("lucent/build"))) { if (!file_exists(storage_path("lucent/build"))) {
return; return;
} }
@@ -42,7 +41,8 @@ class StaticGenerator
exec($cmd); exec($cmd);
} }
private function copyBuildDirectory() :void{ private function copyBuildDirectory(): void
{
if (file_exists(storage_path("lucent/live"))) { if (file_exists(storage_path("lucent/live"))) {
$cmd = "rm -rf " . storage_path("lucent/live"); $cmd = "rm -rf " . storage_path("lucent/live");
exec($cmd); exec($cmd);
+3 -8
View File
@@ -1,13 +1,9 @@
<?php namespace Lucent\StaticGenerator; <?php namespace Lucent\StaticGenerator;
use Illuminate\Contracts\View\View;
class Writer class Writer
{ {
public function __construct( private $logWriter)
public function __construct()
{ {
} }
@@ -27,15 +23,14 @@ class Writer
make_dir_r(pathinfo($filepath, PATHINFO_DIRNAME)); make_dir_r(pathinfo($filepath, PATHINFO_DIRNAME));
} }
file_put_contents($filepath, $html); file_put_contents($filepath, $html);
echo "Path: $path" . PHP_EOL; $logWriter = $this->logWriter;
$logWriter("Path: $path");
} }
public function recordIterator(callable $query, callable $parser, int $skip = 0, $limit = 100): int public function recordIterator(callable $query, callable $parser, int $skip = 0, $limit = 100): int
{ {
// logger("fetching $skip");
$records = $query($limit, $skip); $records = $query($limit, $skip);
$parser($records, $limit, $skip); $parser($records, $limit, $skip);