--- /dev/null
+package App::Clifton::Task;
+
+use Log::Contextual qw(:log);
+use Async::MergePoint;
+use Moo;
+
+extends 'App::Clifton::Component';
+
+has on_finished => (is => 'rw');
+
+has name => (is => 'ro', required => 1);
+
+has body => (is => 'ro', required => 1);
+
+has dependencies => (is => 'ro', default => sub { {} });
+
+has merge_point => (is => 'lazy');
+
+sub _build_merge_point { Async::MergePoint->new }
+
+sub BUILD {
+ my ($self) = @_;
+ my $deps = $self->dependencies;
+ if (my @needs = keys %$deps) {
+ my $mp = $self->merge_point;
+ $mp->needs(@needs);
+ foreach my $key (@needs) {
+ $deps->{$key}->on_finished(sub { $mp->done($key => $_[0]) });
+ }
+ $mp->close(on_finished => $self->_capture_weakself('_schedule_body'));
+ } else {
+ $self->_schedule_body;
+ }
+}
+
+sub _schedule_body {
+ my ($self, %args) = @_;
+ my $fire_body = $self->_capture_weakself('_fire_body');
+ $args{on_finished} = $self->_finished_callback;
+ $self->_schedule(sub { $fire_body->(\%args); });
+}
+
+sub _fire_body {
+ my $self = shift;
+ $self->body->(@_);
+}
+
+sub _finished_callback {
+ my ($self) = @_;
+ $self->_capture_weakself('_schedule_finished');
+}
+
+sub _schedule_finished {
+ my ($self, @args) = @_;
+ if (my $on_finished = $self->on_finished) {
+ $self->_schedule(sub { $on_finished->(@args) });
+ }
+ $self->parent->remove_child($self);
+#$self->$::Dwarn;
+#warn Devel::FindRef::track $self;
+}
+
+1;