Developer-Dashboard
view release on metacpan or search on metacpan
lib/Developer/Dashboard/Collector.pm view on Meta::CPAN
$self->_atomic_write_text( $paths->{last_run}, $timestamp . "\n" );
my $written = $self->update_status(
$name,
sub {
my ($previous) = @_;
my %extra = defined $status_callback ? %{ $status_callback->($previous) || {} } : ();
return {
%{$previous},
%extra,
enabled => exists $result{enabled} ? $result{enabled} : 1,
running => exists $result{running} ? $result{running} : ( exists $extra{running} ? $extra{running} : 0 ),
active_runs => exists $result{active_runs} ? $result{active_runs} : ( exists $extra{active_runs} ? $extra{active_runs} : ( $previous->{active_runs} || 0 ) ),
last_run => $timestamp,
last_completed_at=> $timestamp,
last_exit_code => $result{exit_code},
last_success => $result{exit_code} ? 0 : 1,
last_success_at => $result{exit_code} ? ( $previous->{last_success_at} || undef ) : $timestamp,
last_failure_at => $result{exit_code} ? $timestamp : ( $previous->{last_failure_at} || undef ),
last_started_at => $result{started_at} || $previous->{last_started_at},
output_format => $result{output_format},
timed_out => $result{timed_out} ? 1 : 0,
};
}
);
$self->append_log_entry(
$name,
happened_at => $timestamp,
exit_code => $result{exit_code},
timed_out => $result{timed_out},
stdout => $result{stdout},
stderr => $result{stderr},
);
return $written;
}
# write_status($name, $status)
# Merges and persists collector status metadata without rewriting outputs.
# Input: collector name string and partial status hash reference.
# Output: written status file path.
sub write_status {
my ( $self, $name, $status ) = @_;
return $self->update_status(
$name,
sub {
my ($existing) = @_;
return {
%{$existing},
%{ $status || {} },
};
}
);
}
# update_status($name, $callback)
# Updates one collector status file under an exclusive lock so concurrent
# workers can safely merge active-run counters and lifecycle fields.
# Input: collector name string and callback that receives the current status
# hash reference and returns a replacement hash reference.
# Output: written status file path.
sub update_status {
my ( $self, $name, $callback ) = @_;
die 'Missing collector name' if !defined $name || $name eq '';
die 'Missing collector status callback' if ref($callback) ne 'CODE';
my $paths = $self->collector_paths($name);
my $lock = File::Spec->catfile( $paths->{dir}, '.status.lock' );
open my $lock_fh, '>>', $lock or die "Unable to open $lock: $!";
flock( $lock_fh, LOCK_EX ) or die "Unable to lock $lock: $!";
my $existing = $self->_read_status_file( $paths->{status} ) || {};
my $next = $callback->($existing);
die 'Collector status callback must return a hash reference' if ref($next) ne 'HASH';
my %merged = (
%{$next},
name => $name,
updated_at_epoch => time,
);
return $self->_atomic_write_json( $paths->{status}, \%merged );
}
# mark_run_started($name, $status)
# Records one collector execution start while keeping an accurate active-run
# count for singleton and bounded-multiple loop modes.
# Input: collector name string and optional partial status hash reference.
# Output: written status file path.
sub mark_run_started {
my ( $self, $name, $status ) = @_;
return $self->update_status(
$name,
sub {
my ($existing) = @_;
my $active_runs = ( $existing->{active_runs} || 0 ) + 1;
return {
%{$existing},
%{ $status || {} },
running => 1,
active_runs => $active_runs,
last_started_at => ( $status || {} )->{last_started_at} || $existing->{last_started_at},
};
}
);
}
# mark_run_finished($name, %result)
# Records one collector execution completion while decrementing the active-run
# count under lock so overlapping runs cannot clear another live worker.
# Input: collector name string plus result fields such as exit_code/stdout/stderr.
# Output: written status file path.
sub mark_run_finished {
my ( $self, $name, %result ) = @_;
return $self->write_result(
$name,
%result,
status_callback => sub {
my ($previous) = @_;
my $active_runs = $previous->{active_runs} || 0;
$active_runs-- if $active_runs > 0;
return {
active_runs => $active_runs,
running => $active_runs > 0 ? 1 : 0,
};
},
( run in 0.515 second using v1.01-cache-2.11-cpan-9581c071862 )