Passed
Push — master ( 96ef05...f81447 )
by Darko
09:59
created

TmuxStart::checkTmuxInstalled()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 6
rs 10
cc 2
nc 2
nop 0
1
<?php
2
3
namespace App\Console\Commands;
4
5
use App\Models\Collection;
6
use App\Models\Settings;
7
use App\Services\Tmux\TmuxLayoutBuilder;
8
use App\Services\Tmux\TmuxSessionManager;
9
use Blacklight\ColorCLI;
10
use Illuminate\Console\Command;
11
use Illuminate\Support\Facades\DB;
12
13
class TmuxStart extends Command
14
{
15
    /**
16
     * The name and signature of the console command.
17
     *
18
     * @var string
19
     */
20
    protected $signature = 'tmux:start
21
                            {--session= : Tmux session name}
22
                            {--force : Force start even if session exists}
23
                            {--attach : Attach to session after starting}';
24
25
    /**
26
     * The console command description.
27
     *
28
     * @var string
29
     */
30
    protected $description = 'Start tmux processing session (modernized)';
31
32
    private TmuxSessionManager $sessionManager;
33
34
    private TmuxLayoutBuilder $layoutBuilder;
35
36
    private ColorCLI $colorCli;
37
38
    /**
39
     * Execute the console command.
40
     */
41
    public function handle(): int
42
    {
43
        $this->colorCli = new ColorCLI;
44
45
        try {
46
            $this->colorCli->header('Starting Tmux Processing');
47
48
            // Get session name
49
            $sessionName = $this->option('session')
50
                ?? Settings::settingValue('tmux_session')
51
                ?? config('tmux.session.default_name', 'nntmux');
52
53
            // Initialize services
54
            $this->sessionManager = new TmuxSessionManager($sessionName);
55
            $this->layoutBuilder = new TmuxLayoutBuilder($this->sessionManager);
56
57
            // Check if tmux is installed
58
            if (! $this->checkTmuxInstalled()) {
59
                $this->error('❌ tmux is not installed');
60
61
                return Command::FAILURE;
62
            }
63
64
            // Check if session already exists
65
            if ($this->sessionManager->sessionExists()) {
66
                if (! $this->option('force')) {
67
                    $this->error("❌ Session '{$sessionName}' already exists");
68
                    if ($this->confirm('Would you like to restart it?', false)) {
69
                        $this->call('tmux:stop', ['--session' => $sessionName]);
70
                        sleep(2);
71
                    } else {
72
                        return Command::FAILURE;
73
                    }
74
                } else {
75
                    $this->call('tmux:stop', ['--session' => $sessionName]);
76
                    sleep(2);
77
                }
78
            }
79
80
            // Reset old collections
81
            $this->info('🔄 Resetting old collections...');
82
            $this->resetOldCollections();
83
84
            // Get sequential mode
85
            $sequential = (int) (Settings::settingValue('sequential') ?? 0);
86
            $this->info("📐 Building layout (mode: {$sequential})");
87
88
            // Build the tmux layout
89
            if (! $this->layoutBuilder->buildLayout($sequential)) {
90
                $this->error('❌ Failed to build tmux layout');
91
92
                return Command::FAILURE;
93
            }
94
95
            $this->info('✅ Tmux layout created');
96
97
            // Set running flag
98
            Settings::query()->where('name', 'running')->update(['value' => 1]);
99
            $this->info('✅ Running flag set');
100
101
            // Start monitor in background
102
            $this->info('🚀 Starting monitor...');
103
            $this->startMonitor($sessionName);
104
105
            // Select monitor pane (0.0) so attach lands there
106
            $paneManager = new \App\Services\Tmux\TmuxPaneManager($sessionName);
107
            $paneManager->selectWindow(0);
108
            $paneManager->selectPane('0.0');
109
110
            $this->info("✅ Tmux session '{$sessionName}' started successfully");
111
112
            // Attach if requested
113
            if ($this->option('attach')) {
114
                $this->info('📎 Attaching to session...');
115
                $this->sessionManager->attachSession();
116
            } else {
117
                $this->info("💡 To attach to the session, run: tmux attach -t {$sessionName}");
118
                $this->info('💡 Or use: php artisan tmux:attach');
119
            }
120
121
            return Command::SUCCESS;
122
123
        } catch (\Exception $e) {
124
            $this->error('❌ Failed to start tmux: '.$e->getMessage());
125
            logger()->error('Tmux start error', [
126
                'message' => $e->getMessage(),
127
                'trace' => $e->getTraceAsString(),
128
            ]);
129
130
            return Command::FAILURE;
131
        }
132
    }
133
134
    /**
135
     * Check if tmux is installed
136
     */
137
    private function checkTmuxInstalled(): bool
138
    {
139
        $result = \Illuminate\Support\Facades\Process::timeout(5)
140
            ->run('which tmux 2>/dev/null');
141
142
        return $result->successful() && str_contains($result->output(), 'tmux');
143
    }
144
145
    /**
146
     * Reset old collections
147
     */
148
    private function resetOldCollections(): void
149
    {
150
        $delayTime = (int) (Settings::settingValue('delaytime') ?? 2);
151
152
        try {
153
            DB::transaction(function () use ($delayTime) {
154
                $count = Collection::query()
155
                    ->where('dateadded', '<', now()->subHours($delayTime))
156
                    ->update(['dateadded' => now()]);
157
158
                if ($count > 0) {
159
                    $this->info("  ✓ Reset {$count} expired collections");
160
                } else {
161
                    $this->info('  ✓ No collections needed resetting');
162
                }
163
            }, 10);
164
165
        } catch (\Exception $e) {
166
            $this->warn('  ⚠ Failed to reset collections: '.$e->getMessage());
167
        }
168
    }
169
170
    /**
171
     * Start the monitor process
172
     */
173
    private function startMonitor(string $sessionName): void
174
    {
175
        $paneManager = new \App\Services\Tmux\TmuxPaneManager($sessionName);
176
177
        // Priority: new monitor > old monitor > artisan command
178
        $newMonitor = base_path('app/Services/Tmux/Scripts/monitor.php');
179
        $oldMonitor = base_path('misc/update/tmux/monitor.php');
180
181
        if (file_exists($newMonitor)) {
182
            // Use the new modernized monitor script
183
            $command = "php {$newMonitor}";
184
            $this->info('  ✓ Using modernized monitor script');
185
        } elseif (file_exists($oldMonitor)) {
186
            // Fall back to original monitor script
187
            $command = "php {$oldMonitor}";
188
            $this->warn('  ⚠ Using legacy monitor.php (consider updating)');
189
        } else {
190
            // Last resort: use artisan command (not ideal for pane)
191
            $artisan = base_path('artisan');
192
            $command = "php {$artisan} tmux:monitor --session={$sessionName}";
193
            $this->warn('  ⚠ Using artisan command (not recommended for pane)');
194
        }
195
196
        // Spawn monitor in pane 0.0
197
        $paneManager->respawnPane('0.0', $command);
198
    }
199
}
200