+sub update_status {
+ my ($self) = @_;
+ my @jobs = $self->jobs->search({'me.private' => 0}, {cache => 1, prefetch => 'problem', order_by => 'me.id'})->all;
+
+ my %private;
+ my %hash;
+ for (@jobs) {
+ my $pb = $_->get_column('problem');
+ $private{$pb} //= $_->problem->private;
+ next if $private{$pb};
+ $hash{$pb, $_->get_column('owner')} = [$_->id, $_->result ? 0 : 1];
+ }
+
+ my @problem_statuses = map { [split ($;), @{$hash{$_}} ] } keys %hash;
+
+ my @contest_statuses = map {
+ my $contest = $_->id;
+ map { [$contest, $_->{user}, $_->{score}, $_->{rank}] } $_->standings
+ } $self->contests->all;
+
+ my $txn = sub {
+ $self->problem_statuses->delete;
+ $self->problem_statuses->populate([[qw/problem owner job solved/], @problem_statuses]);
+ $self->contest_statuses->delete;
+ $self->contest_statuses->populate([[qw/contest owner score rank/], @contest_statuses]);
+ };
+
+ $self->txn_do($txn);
+}
+
+my @PURGE_HOSTS = exists $ENV{PURGE_HOSTS} ? split ' ', $ENV{PURGE_HOSTS} : ();
+my $ht = HTTP::Tiny->new;
+
+sub purge {
+ $ht->request(PURGE => "http://$_$_[0]") for @PURGE_HOSTS;
+}
+