2024-05-25 12:25:57 +00:00
< ? php
namespace App\Jobs ;
use Carbon\Carbon ;
use Illuminate\Bus\Queueable ;
use Illuminate\Contracts\Queue\ShouldQueue ;
use Illuminate\Database\Eloquent\Collection ;
use Illuminate\Foundation\Bus\Dispatchable ;
use Illuminate\Queue\InteractsWithQueue ;
use Illuminate\Queue\SerializesModels ;
use Illuminate\Support\Facades\DB ;
use Illuminate\Support\Facades\Log ;
use Illuminate\Support\Facades\Notification ;
2024-05-26 11:41:02 +00:00
use App\Classes\FTN\Message ;
2024-06-12 13:12:51 +00:00
use App\Models\ { Address , Domain , System };
2024-05-25 12:25:57 +00:00
use App\Notifications\Echomails\AbsentNodes ;
use App\Notifications\Emails\NodeMarkedDown as NodeMarkedDownEmail ;
use App\Notifications\Netmails\NodeMarkedDown as NodeMarkedDownNetmail ;
use App\Notifications\Emails\NodeMarkedHold as NodeMarkedHoldEmail ;
use App\Notifications\Netmails\NodeMarkedHold as NodeMarkedHoldNetmail ;
use App\Notifications\Emails\NodeDelisted as NodeDelistedEmail ;
use App\Notifications\Netmails\NodeDelisted as NodeDelistedNetmail ;
class AddressIdle implements ShouldQueue
{
use Dispatchable , InteractsWithQueue , Queueable , SerializesModels ;
private const LOGKEY = 'JAI' ;
private ? Address $ao ; // System address
private Domain $do ; // Domain we are processing
/**
* Create a new job instance .
*/
public function __construct ( Domain $do , Address $ao = NULL )
{
$this -> do = $do ;
$this -> ao = $ao ;
}
/**
* Execute the job .
*/
public function handle () : void
{
$result = collect ();
// Delist DOWN nodes
2024-09-22 07:33:08 +00:00
if ( config ( 'fido.idle.delist' )) {
$age = Carbon :: now () -> subDays ( config ( 'fido.idle.delist' ));
foreach ( $this -> old ( $this -> do , config ( 'fido.idle.delist' ), Address :: NODE_DOWN , $this -> ao ) as $ao ) {
// Only delist system that has been marked down
// Only delist them if its been 14 days since they were marked DOWN
if (( ! $ao -> is_down ) || ( $ao -> updated_at -> greaterThan ( Carbon :: now () -> subWeeks ( 2 ))))
continue ;
// Validate that the last seen was infact that long ago
if ( $ao -> system -> last_seen -> greaterThan ( $age ))
continue ;
Log :: info ( sprintf ( '%s:- Delisting [%s], not seen for [%d] days' , self :: LOGKEY , $ao -> ftn , config ( 'fido.idle.delist' )));
$contact = FALSE ;
// Remove echomail not collected from echomail_seenby
DB :: table ( 'echomail_seenby' )
-> where ( 'address_id' , $ao -> id )
-> whereNotNull ( 'export_at' )
-> whereNull ( 'sent_at' )
-> delete ();
// Remove FLAG_INTRANSIT from netmail that hasnt been delivered
DB :: table ( 'netmails' )
-> where ( 'tftn_id' , $ao -> id )
-> whereRaw ( sprintf ( '(flags & %d) > 0' , Message :: FLAG_INTRANSIT ))
-> update ([ 'flags' => DB :: raw ( sprintf ( '(flags & ~%d)' , Message :: FLAG_INTRANSIT ))]);
// Remove files not collected
DB :: table ( 'file_seenby' )
-> where ( 'address_id' , $ao -> id )
-> whereNotNull ( 'export_at' )
-> whereNull ( 'sent_at' )
-> delete ();
// Remove subscribed echoareas
$ao -> echoareas () -> detach ();
// Remove subscribed fileareas
$ao -> fileareas () -> detach ();
$ao -> active = FALSE ;
$ao -> validated = FALSE ;
$ao -> save ();
// Email Alert
if ( $ao -> system -> users -> count ()) {
Notification :: send ( $ao -> system -> users , new NodeDelistedEmail ( $ao -> withoutRelations ()));
$contact = TRUE ;
}
// Netmail Alert (to othernet network address)
if ( $ao -> system -> uncommon () -> count ()) {
Notification :: route ( 'netmail' , $ao -> system -> uncommon () -> first () -> withoutRelations ()) -> notify ( new NodeDelistedNetmail ( $ao -> withoutRelations ()));
$contact = TRUE ;
}
$ao -> contacted = $contact ;
$result -> push ( $ao );
2024-05-25 12:25:57 +00:00
}
}
// Mark nodes DOWN
2024-09-22 07:33:08 +00:00
if ( config ( 'fido.idle.down' )) {
$age = Carbon :: now () -> subDays ( config ( 'fido.idle.down' ));
foreach ( $this -> old ( $this -> do , config ( 'fido.idle.down' ), Address :: NODE_HOLD , $this -> ao ) as $ao ) {
// Only mark down system that has been marked down
// Only mark down them if its been 14 days since they were marked HOLD
if (( ! $ao -> is_hold ) || ( $ao -> updated_at -> greaterThan ( Carbon :: now () -> subWeeks ( 2 ))))
continue ;
// Validate that the last seen was infact that long ago
if ( $ao -> system -> last_seen -> greaterThan ( $age ))
continue ;
Log :: info ( sprintf ( '%s:- Marking [%s] as DOWN, not seen for [%d] days' , self :: LOGKEY , $ao -> ftn , config ( 'fido.idle.down' )));
$contact = FALSE ;
// Email Alert
if ( $ao -> system -> users -> count ()) {
Notification :: send ( $ao -> system -> users , new NodeMarkedDownEmail ( $ao -> withoutRelations ()));
$contact = TRUE ;
}
// Netmail Alert (to othernet network address)
if ( $ao -> system -> uncommon () -> count ()) {
Notification :: route ( 'netmail' , $ao -> system -> uncommon () -> first () -> withoutRelations ()) -> notify ( new NodeMarkedDownNetmail ( $ao -> withoutRelations ()));
$contact = TRUE ;
}
// Mark as DOWN
$ao -> role &= ~ Address :: NODE_HOLD ;
$ao -> role |= Address :: NODE_DOWN ;
$ao -> save ();
$ao -> contacted = $contact ;
$result -> push ( $ao );
2024-05-25 12:25:57 +00:00
}
}
2024-09-08 10:39:10 +00:00
// @todo Make sure we only process addresses that we are responsible for, eg: 1/999 shouldnt have been processed even though 3/999 as eligible (and they are were connected to the same system)
2024-05-25 12:25:57 +00:00
// Mark nodes as HOLD
2024-09-22 07:33:08 +00:00
if ( config ( 'fido.idle.hold' )) {
$age = Carbon :: now () -> subDays ( config ( 'fido.idle.hold' ));
foreach ( $this -> old ( $this -> do , config ( 'fido.idle.hold' ), Address :: NODE_ALL , $this -> ao ) as $ao ) {
// Ignore any systems that are a Discoverd System
if ( $ao -> system -> name === System :: default ) {
Log :: alert ( sprintf ( '%s:! Ignoring HOLD for discovered System [%s]' , self :: LOGKEY , $ao -> ftn ));
continue ;
}
// Ignore any systems already marked hold or down
if ( $ao -> role & ( Address :: NODE_DOWN | Address :: NODE_HOLD ))
continue ;
// Validate that the last seen was infact that long ago
if ( $ao -> system -> last_seen -> greaterThan ( $age ))
continue ;
$contact = FALSE ;
Log :: info ( sprintf ( '%s:- Marking [%s] as HOLD, not seen for [%d] days' , self :: LOGKEY , $ao -> ftn , config ( 'fido.idle.hold' )));
// Email Alert
if ( $ao -> system -> users -> count ()) {
Notification :: send ( $ao -> system -> users , new NodeMarkedHoldEmail ( $ao -> withoutRelations ()));
$contact = TRUE ;
}
// Netmail Alert (to othernet network address)
if ( $ao -> system -> uncommon () -> count ()) {
Notification :: route ( 'netmail' , $ao -> system -> uncommon () -> first () -> withoutRelations ()) -> notify ( new NodeMarkedHoldNetmail ( $ao -> withoutRelations ()));
$contact = TRUE ;
}
// Mark as DOWN
$ao -> role |= Address :: NODE_HOLD ;
$ao -> save ();
$ao -> contacted = $contact ;
$result -> push ( $ao );
2024-06-12 13:12:51 +00:00
}
2024-05-25 12:25:57 +00:00
}
if ( $result -> count ())
Notification :: route ( 'echomail' , $this -> do -> nodestatusarea ) -> notify ( new AbsentNodes ( $result ));
}
private function old ( Domain $do , int $days , int $flags = 0 , Address $ao = NULL ) : Collection
{
2024-09-22 07:33:08 +00:00
// Ignore dates that are zero
if ( ! $days )
return collect ();
2024-05-25 12:25:57 +00:00
$age = Carbon :: now () -> subDays ( $days ) -> endOfDay ();
return Address :: select ([
2024-09-09 10:16:14 +00:00
'addresses.id' ,
'system_id' ,
'zone_id' ,
'region_id' ,
'host_id' ,
'node_id' ,
'point_id' ,
2024-05-25 12:25:57 +00:00
'addresses.active' ,
2024-09-09 10:16:14 +00:00
'hub_id' ,
'role' ,
2024-05-25 12:25:57 +00:00
'addresses.updated_at' ,
])
2024-09-09 10:16:14 +00:00
-> activeFTN ()
2024-05-25 12:25:57 +00:00
-> where ( 'systems.active' , TRUE )
2024-09-09 10:16:14 +00:00
-> where ( fn ( $query ) => $query -> where ( 'point_id' , 0 ) -> orWhereNull ( 'point_id' ))
-> whereIn ( 'addresses.id' , our_nodes ( $do ) -> pluck ( 'id' ))
2024-05-25 12:25:57 +00:00
-> when ( $ao , fn ( $query ) => $query -> where ( 'addresses.id' , $ao -> id ))
2024-09-09 10:16:14 +00:00
-> where ( fn ( $q ) => $q -> where ( 'last_session' , '<' , $age ) -> orWhereNull ( 'last_session' ))
-> whereRaw ( sprintf ( '((role IS NULL) OR (role=0) OR ((role & %d) > 0))' , $flags ))
-> whereRaw ( sprintf ( '((role & %d) = 0)' , Address :: NODE_KEEP ))
-> join ( 'systems' ,[ 'systems.id' => 'addresses.system_id' ])
2024-05-25 12:25:57 +00:00
-> ftnOrder ()
-> with ([ 'system' , 'zone.domain' ])
-> dontCache ()
-> get ();
}
}