--- /dev/null
+package App::Clifton::Component;
+
+# define this up here to avoid uninitialised warnings
+sub _debug_self {
+ my ($self, $args) = @_;
+ "${self}: ".join ', ', map "$_ => ".$args->{$_}, keys %$args;
+}
+
+use Log::Contextual qw(:log);
+use Moo;
+
+extends 'IO::Async::Notifier';
+
+sub BUILD {
+ my ($self, $args) = @_;
+ log_debug {
+ "Constructing "._debug_self($self, $args);
+ };
+ if (my $parent = $args->{parent_component}) {
+ $parent->add_child($self);
+ }
+}
+
+sub configure {
+ # If we called the superclass method, any ->new params that were populated
+ # into attributes would cause a croak. While the loss of error checking is
+ # annoying I've got other things to fix right now.
+}
+
+sub _new_child {
+ my ($self, $class, $args) = @_;
+ $class->new(%{$args||{}}, parent_component => $self);
+}
+
+sub _schedule {
+ my ($self, $code) = @_;
+ $self->get_loop->later($code);
+}
+
+sub DESTROY {
+ my ($self) = @_;
+ log_debug { "Destroying "._debug_self($self, $self) };
+}
+
+1;