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": {
"file": "assets/main-1FLcNLEV.js",
"file": "assets/main-D9joEh0I.js",
"name": "main",
"src": "main.js",
"isEntry": true,
"css": [
"assets/main-U24QISX_.css"
"assets/main-BnJW41Dx.css"
]
}
}
+14 -1
View File
@@ -8,6 +8,7 @@
$: date = "";
$: logs = "";
let anchorEl;
let inProgress = false;
function connect() {
@@ -18,6 +19,7 @@
const data = JSON.parse(event.data);
date = data.date;
logs = data.logs;
anchorEl.scrollIntoView()
}
eventSource.onerror = (e) => {
console.log(e)
@@ -65,6 +67,17 @@
</div>
<pre>{logs}</pre>
<pre class="logs">{logs}
<div bind:this={anchorEl}>&nbsp;</div>
</pre>
</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 isCreateMode;
export let validationErrors;
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
$: errorMessage = getErrorMessage(validationErrors, field.name);
export let id;
let wrapperDiv;
let pickerInput;
let pickerInstance;
let flatpickrOptions = {
appendTo: wrapperDiv,
static: true,
allowInput: true,
altInput: true,
altFormat: "Y-m-d H:i:S",
@@ -40,7 +44,7 @@
});
</script>
<div class="mb-0">
<div class="mb-0" bind:this={wrapperDiv}>
<input
type="text"
@@ -67,7 +67,7 @@
class=" button"
on:click={(e) =>
createInlineReference(e, schema.name)}
>{schema.name}
>{schema.label}
</button>
{/each}
@@ -78,7 +78,7 @@
<button
class="button"
on:click={(e) => openBrowseModal(e, schema.name)}
>{schema.name}
>{schema.label}
</button>
{/each}
+1
View File
@@ -3,6 +3,7 @@
margin: 20px 0 20px;
display: flex;
gap: 4px;
flex-wrap: wrap;
.tab{
list-style: none;
+3
View File
@@ -105,3 +105,6 @@ a {
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']);
$userCommands = [];
foreach (config("lucent.commands") as $signature => $desc) {
foreach (config("lucent.commands") ?? [] as $signature => $desc) {
$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 {
protected $connection = 'lucentDb';
protected $connection = 'lucentdb';
/**
* Run the migrations.
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
protected $connection = 'lucentDb';
protected $connection = 'lucentdb';
/**
* Run the migrations.
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration {
protected $connection = 'lucentDb';
protected $connection = 'lucentdb';
/**
* Run the migrations.
*
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration {
protected $connection = 'lucentDb';
protected $connection = 'lucentdb';
/**
* Run the migrations.
*
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration {
protected $connection = 'lucentDb';
protected $connection = 'lucentdb';
/**
* Run the migrations.
*
@@ -6,7 +6,7 @@ use Illuminate\Support\Facades\Schema;
return new class extends Migration {
protected $connection = 'lucentDb';
protected $connection = 'lucentdb';
/**
* 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\Http\Request;
use Lucent\Channel\ChannelService;
use Lucent\Command\CommandRepo;
use Lucent\Command\CommandService;
use Lucent\Svelte\Svelte;
class BuildController extends Controller
{
public function __construct(
public readonly Svelte $svelte,
public readonly ChannelService $channelService,
private readonly Svelte $svelte,
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)
{
$commandSignature = $request->route("signature");
$buildLogFile = $this->getLogFile($commandSignature);
$pidFile = $this->getPidFile($commandSignature);
if (file_exists($buildLogFile)) {
unlink($buildLogFile);
}
if (file_exists($pidFile)) {
unlink($pidFile);
}
$this->commandService->run($commandSignature);
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
@@ -55,8 +48,10 @@ class BuildController extends Controller
$commandSignature = $request->route("signature");
return response()->stream(function () use ($commandSignature) {
while (true) {
$commandLogItem = $this->commandRepo->findBySignature($commandSignature);
$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"]);
echo 'data: ' . json_encode($data);
@@ -64,19 +59,8 @@ class BuildController extends Controller
ob_flush();
flush();
$pidFile = $this->getPidFile($commandSignature);
if (file_exists($pidFile)) {
$pid = file_get_contents($pidFile);
} else {
break;
}
if (empty($pid)) {
break;
}
if (!file_exists("/proc/$pid")) {
logger($this->commandService->commandIsRunning($commandLogItem->pid));
if (!$this->commandService->commandIsRunning($commandLogItem->pid)) {
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']);
});
$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(),
"pgsql" => new PgsqlDatabaseGraph(),
};
+14 -14
View File
@@ -3,38 +3,37 @@
use Carbon\Carbon;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Lucent\Command\CommandService;
use Throwable;
class StaticGenerator
{
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
{
echo "Start ".Carbon::now()->format("Y-m-d H:i:s").PHP_EOL;
$logWriter = $this->commandService->logWriter($signature);
$logWriter("Start " . Carbon::now()->format("Y-m-d H:i:s"));
$this->removeBuildDirectory();
echo "Removing previous data".PHP_EOL;
$logWriter("Removing previous data");
try {
$callback($this->writer);
$callback(new Writer($logWriter));
} 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();
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"))) {
return;
}
@@ -42,7 +41,8 @@ class StaticGenerator
exec($cmd);
}
private function copyBuildDirectory() :void{
private function copyBuildDirectory(): void
{
if (file_exists(storage_path("lucent/live"))) {
$cmd = "rm -rf " . storage_path("lucent/live");
exec($cmd);
+3 -8
View File
@@ -1,13 +1,9 @@
<?php namespace Lucent\StaticGenerator;
use Illuminate\Contracts\View\View;
class Writer
{
public function __construct()
public function __construct( private $logWriter)
{
}
@@ -27,15 +23,14 @@ class Writer
make_dir_r(pathinfo($filepath, PATHINFO_DIRNAME));
}
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
{
// logger("fetching $skip");
$records = $query($limit, $skip);
$parser($records, $limit, $skip);