App-karr

 view release on metacpan or  search on metacpan

lib/App/karr/Foundation/State.pm  view on Meta::CPAN

# ABSTRACT: karr-foundation per-repo state — lock file, JSON state, cooldown backoff

package App::karr::Foundation::State;
our $VERSION = '0.401';
use Moo;
use Path::Tiny;
use JSON::MaybeXS qw( encode_json decode_json );
use Try::Tiny;


has foundation => (
  is       => 'ro',
  weak_ref => 1,
  required => 1,
);

# ---------------------------------------------------------------------------
# Lock file
# ---------------------------------------------------------------------------

sub _lock_file { path( $_[1]->child('.karr.lock') ) }

sub _lock_held {
  my ( $self, $repo ) = @_;
  my $lock = $self->_lock_file( $repo );
  return 0 unless $lock->exists;
  my $pid = $lock->slurp_utf8;
  chomp $pid;
  return 0 unless $pid =~ /^\d+$/;
  # Check if PID is alive
  return kill( 0, $pid ) ? 1 : 0;
}

sub _acquire_lock {
  my ( $self, $repo ) = @_;
  return if $self->foundation->dry_run;
  $self->_lock_file( $repo )->spew_utf8( "$$\n" );
}

sub _release_lock {
  my ( $self, $repo ) = @_;
  return if $self->foundation->dry_run;
  my $lock = $self->_lock_file( $repo );
  $lock->remove if $lock->exists;
}

# ---------------------------------------------------------------------------
# State file
# ---------------------------------------------------------------------------

sub _state_file { path( $_[1]->child('.karr.state') ) }

sub _state_get {
  my ( $self, $repo, $key ) = @_;
  my $state_file = $self->_state_file( $repo );
  return undef unless $state_file->exists;
  my $data = try { decode_json( $state_file->slurp_utf8 ) } catch { {} };
  return $data->{$key};
}

sub _state_set {
  my ( $self, $repo, %kv ) = @_;
  return if $self->foundation->dry_run;
  my $state_file = $self->_state_file( $repo );
  my $data = {};
  if ( $state_file->exists ) {
    $data = try { decode_json( $state_file->slurp_utf8 ) } catch { {} };
  }



( run in 0.520 second using v1.01-cache-2.11-cpan-5fbc6bb55f2 )