►
From YouTube: Grafana Agent Community Call 2022-05-18
Description
No description was provided for this meeting.
If this is YOUR meeting, an easy way to fix this is to add a description to your video, wherever mtngs.io found it (probably YouTube).
A
Hello,
hello,
welcome
to
the
griffana
agent
community
call
on
may
the
18th,
and
today
we
got
a
few
topics.
Well,
we
have
one
topic
and
we
are
going
to
be
digging
into
a
review
of
the
agent
flow
pr
that
robert
kicked
off.
So
unless
anyone
has
any
questions
to
bring
up
before
that.
A
All
right
and
we
will
jump
into
robert
if
you
want
to
take
the
lead.
B
Sure
so
last
month
we
kind
of
talked
about
asian
flow
in
general
and
talked
about
kind
of,
like
the
two
main
approaches,
we're
thinking
of
exploring
one
being
like
an
actor
model
where
different
actors
are
different
components
and
they
can
interact
with
each
other
by
sending
messages
and
the
other
one
being
like
more
of
like
a
declarative
actor
model
kind
of
where
we
use
hcl
and
expressions
to
bind
components
together
like
through
their
values.
B
We
prototyped
both
of
those
approaches
internally
and
kind
of
agreed
to
focus
on
the
hcl
based
approach.
For
now
that
doesn't
mean,
like
you
know.
What
we
want
to
do
is
pick
one
ship
ship
it
like
an
mvp
and
then
get
feedback
and
then
figure
out.
Is
this
the
right
approach,
or
should
we
try
actors
again
or
should
we
like
try
something
else
entirely?
We
should
should.
We
do
nothing
always
always
a
good
choice,
but
for
now
we
decided
to
at
least
focus
our
efforts
on
the
hcl
aspect.
B
So
part
of
the
mvp
is
going
to
be
focused
around
metric
based
components
and
the
first
part
of
that
is
kind
of
finalizing.
The
controller,
which
kind
of
runs
runs
the
the
hdl
graph
and
and
kind
of
manages
all
the
components
that
are
running.
So
we
have
a.
B
We
have
a
pr
that
I
opened
for
that
and
for
the
initial
controller
which
I'm
going
to
screen
share
and
we
can
just
kind
of
do
like
a
live
code
review
of
what
we
have
and
maybe
get
some
feedback,
so
we
can
fix
it
before
it
gets
merged.
B
Give
me
one
moment:
actually,
here's
all
here's
what
I'll
start
I'll
start
with
showing
the
pr
description,
because
I
think
that
might
be
useful.
B
All
right
and
close,
google
drive
okay,
so
controller
is
a
weird
term.
I
think,
like
it's
kind
of
hard
to
say
what
a
controller
is.
I
know
like
in
kubernetes.
The
control
plane
is
the
idea
of
having
like
a
suite
of
things,
which
I'm
trying
to
try
to
explain,
and
I
actually
don't
know
like.
I
don't
know
what
a
controller
is.
B
I
think
you
can
kind
of
intuit
what
a
controller
might
mean,
but
in
this
context
the
flow
controller
is
the
thing
that
a
loads
hcl
files,
populates
a
dag
and
like
runs
components
and
updates
them
when,
whenever
they
change
so
at
a
like
the
lowest
level,
a
component
is
going
to
be
like
an
individual
unit
of
business
logic.
For
example,
getting
something
out
of
vault
would
be
a
component
or
scraping
prometheus
metrics
from
a
target.
B
That
would
be
a
component
and
each
component
has
a
set
of
input
arguments
and
it
can
optionally
export
like
fields
that
other
components
could
use.
So
an
input
argument
for,
like
the
vault
example,
would
be
like
your
vault
key
and
then
the
optional
exported
field
would
be
the
value
of
that
vault
key.
That
got
retrieved,
not
all
components,
will
export
something
so
like
something
doing
remote
write,
probably
wouldn't
export
things
for
other
components
to
use,
but
components
that
do
have
something
to
export.
You
know
can
can
do
that.
B
The
exports
can
change
over
the
process's
lifetime.
So
again,
with
with
like
a
with
the
vault
thing,
maybe
it
refreshes
every
10
seconds,
for
example,
then,
if
the
the
output
or
the
default
value
of
that
key
changes,
its
exports
will
be
updated
to
the
current
state
of
the
value
whenever
you
do
a
refresh
and
any
component
any
component
which
is
referencing.
B
That
did
I
hit
rejecter
that
I
had
accept
on
that
person's
joining
I
hit
accept.
Okay,
there
you
go
there,
it
goes
and
then
any
component
which
is
referencing
the
the
output
of
the
vault
key,
would
would
then
be
updated
to
reflect
the
current
state
of
things.
So
that's
a
high
level.
What
like
what
a
component
is
so
then
to
specify
component
like
I
said,
we're
using
hcl
here.
So
I
should
I
should
have.
I
shouldn't
have
used
the
ball
example.
B
B
So
this
might
be
how
you
configure
that
component
like
it's
in
the
remote
group,
the
type
of
remote
is
http
and
you
can
give
it
like
a
user
identified
name
here,
I'm
just
calling
it
get
url
just
arbitrarily,
so
every
every
10
seconds
we
we
get
this
url
and
then
it
would
export,
for
example,
like
a
response
body
field,
so
another
component,
another
remote
http
component,
could
you
know,
use
the
response
body
as
its
input
for
the
url.
B
B
We
showed
like
a
much
more
useful
example
of
this.
Let's
see
if
I
can
bring
that
up
real
quick.
B
So
in
the
original
example,
we
kind
of
had
that
remote
http,
like
it
gives
you
an
api
key
back
and
then
in
the
remote
right.
We
bind
the
password
to
to
that
api
key.
So
this
is
like
a
much
more
realistic
example
of
how
you
might
use
these
remote
components
to
get
remote
values
from
from
some
store.
So
we
could
imagine
like
a
remote
vault
in
a
remote
s3
and
they
can
be
any
string
and
they
can
be
used
for
anything
that
accepts
a
string.
B
So
one
one
interesting
point
to
make
is
that,
like
these,
this
composes
like
a
fully
qualified
identifier
for
a
component,
so
we
would
say
that
there
is
one
instance
of
remote
http
get
second
url
running
and
that
name
would
have
to
be
globally
unique.
So
you
couldn't
have
a
remote
http.
You
could
have
two
remote
http
get
second
urls,
but
you
could
have
one
remote
http
get
second
url,
then
remote
http
get
another
url
like
that,
would
allow
them
to
be
distinct.
B
However,
some
components
won't
support
this
user
identifier,
which
means
there
can
only
ever
be
one
of
them
forever
for
the
process
lifetime.
A
good
example
of
that
would
be
node
exporter
where,
because
of
kind
of
well
actually
c
advisor
would
be
a
good
one,
because,
because
of
how
like
c
advisor
was
designed,
you
can't
really
run
two
of
them
in
one
process,
so
that
would
be
one
component
which
wouldn't
have
a
user
identifier
and
in
the
file
you
would
just
say
like
node,
exporter
or
c
advisor.
B
Yep,
okay,
cool,
so
the
implementation
of
the
controller,
there's
kind
of
a
few
parts.
There
is
a
loader
which
will
given
like
a
set
of
hcl
blocks.
It'll
construct
a
the
dag
and
it'll
also
evaluate
components
within
that
dag.
After,
like
a
wire's
dependencies
together,
then
there's
the
scheduler
which,
given
a
set
of
components
that
should
be
running
it'll,
just
keep
them
running.
It'll
manage
guru
teams
for
them,
so
as
components
run,
they
might
export
new
states
and
if
that
were
to
happen,
they
need
to
be
put
in
a
queue
for
later
processing.
B
So
that's
this
queue.
Matt
go
ahead.
B
So
good
question:
it's
unordered
in
the
dequeueing
is
random,
like
you'll
dq,
any
anything
that
got
queued.
B
I'll
show
you
how
it
got
unordered,
but
like
really
all
we
needed
was
like
a
set
of
things
to
process
later
the
order
didn't
really
matter,
and
so
the
easiest
thing
to
do
was
a
map.
So
because
you
can't
like
read
from
a
map
the
same
way
every
single
time
it's
it
becomes
an
audio
queue
that
can
change
over
time.
If
there's
a
reason,
it
needs
to
be
ordered,
but
it
does
mean
anything
that
changes
might
not
really
be
evaluated
right
away.
Gotcha.
B
So
once
you
know,
there'll
be
a
go
routine,
which
reads
from
the
queue
over
time
and
then,
as
things
are,
dequeued
they'll
be
reevaluated,
and
then
anything
that
depends
on
them
will
be
reevaluated
so
that,
like
their
changes
propagate
to
things
that
reference
them,
the
last
part
of
it
is
the
component
node,
so
that
this
is
kind
of
the
wrapper
around
an
individual
component
within
the
dag.
It
manages
that
component
and
then
like
it,
you
know,
exposes
a
different
api
over
over
that
component.
B
All
right.
So
I
want
to
talk
a
little
bit
about
hcl
hcl
uses
a
type
system
called
go
cty.
I
said
duct
typed,
but
now
now
that
it's
this
is
going
on
youtube.
I
don't
know
if
duct
tape
is
actually
correct,
but
I
think
it's
so
when
you
evaluate
something
in
hcl,
you
need
an
eval
context
and
that
context
lists
all
the
variables
which
are
accessible
to
the
thing
being
evaluated
and
all
the
functions
which
are
being
which
are
accessible
to
the
thing
being
evaluated.
B
So,
for
example,
you
could
have
like
a
root,
scoped,
eval
context,
which
has
all
your
functions
and
then
a
child
scope
of
that
which
has
all
the
values
of
all
the
components
that
are
currently
running,
and
that
is
exactly
what
we're
doing
where
we
have
a
eval
context,
which
is
all
the
functions,
and
then
we
have
something
called
a
value
cache
which
caches
the
current
arguments
and
exports
for
all
the
components
and
then
builds
in
the
eval
context
from
like
the
cache
values.
B
So
that
means
when
we
evaluate
another
component,
they
have
access
to
everything,
any
value
that
they
might
want
to
use
from.
Another
component
that
was
running
does
that
make
sense
the
important
the
important
bit
of
the
of
the
cache
is
that
you
always
evaluate
the
first
component.
B
You
evaluate
has
to
have
no
dependencies,
so
you
have
to
make
sure
that
the
dependencies
are
always
evaluated
first
before
you
evaluate
the
things
that
depend
on
them,
otherwise
their
values
will
not
exist
in
the
value
cache
and
that's
how
we
use
that's
how
we
like
consume
the
dag
figuring
out.
What
that
evaluation
order
is
any
questions
about
that.
B
B
None
of
hashicorp
stuff
actually
use
capsule
types,
but
I
think
it's
really
really
interesting
for
flow,
because
it
does
mean
we
can
do
something
like
in
the
original
example,
this
metrics
forwarder,
which
is
a
wow
and
remote,
writes
it
exports
a
receiver
which
is
a
go
interface
where
things
doing
scraping
can
just
push
metrics
to
it.
So
this
is
sending
to
that
receiver.
B
B
Like
complicated,
go
objects,
the
the
the
other
way
of
doing
this
without
capital
types
would
be
handles.
I
don't
really
like
that
idea,
because
then
it
means,
like
the
implementation
of
components,
has
to
get
a
little
more
annoying
where
you
have
to
like
look
up.
What
a
handle
is
and
get
the
actual
value
so
being
able.
B
B
So
there's
a
lot.
We
haven't
done
with
the
controller
this
pr,
like
it's
not
being
used
anywhere,
I'm
just
showing
you
as
a
base.
Example,
this
used
to
include,
like
log
level,
long
format
which
wasn't
used
that
got
removed.
So
this
this
needs
to
be
removed
as
a
like
future
thing,
but
we
do
need
logging
like
we.
B
But
we
need
to
be
able
to
specify
what
the
log
level
is
at
the
the
file.
Also,
this
doesn't
have
tls
settings
for
the
server
which
you
know
we'll
do
that
later.
Also,
it
doesn't
detect
reference
cycles
which
are
invalid,
eventually
we'll
add
cycle
detection
and
prevent
those
files
from
being
loaded.
B
This
also
doesn't
come
with
any
components
other
than
like
test
components
which
I
built
for
testing.
Also
there
can
only
be
one
hcl
file
at
some
point.
We
might
want
multiple
file
support,
like
modules
or
whatever,
like
includes
don't
have
those
yet
then
this
is
also
no
longer
true,
but
I'll
I'll
explain
that
later,
okay,
that
was
that
was
me
reading
the
pr
description.
So,
let's
start
with
questions
before
I
go
into
any
code,
pascals.
B
Yeah,
but
I
also
think
if
this
pr
gets
merged
like
I
don't
I
don't
think.
Well,
I
guess
that's
up
for
up
for
discussion,
but
I
personally
don't
think
this
needs
to
wait
unless
there's
like
a
really
big
issue
with
it
like
we
can
just
iterate
over
time
and
like
if
this
was
merged,
we
could
build
build
components
now.
B
B
B
B
All
right,
I'm
gonna,
start
with
the
component
package,
because
this
goes
over
some
details.
A
lot
of
this
I
kind
of
already
described
in
terms
of
like
you
know,
components
have
arguments
in
exports,
so
I'm
just
redescribing
here
in
a
lot
more
detail,
I'm
also
requesting
for
now
that
there
are
some
reserved
fields.
We
don't
actually
check
for
this.
It's
not
it's
not
being
validated
here,
but
at
a
documentation
level
we're
suggesting
that
these
are
reserved
and
if
you
try
using
them,
it'll
eventually
be
rejected.
B
So
for
each
is
something
that
terraform
uses
for
like
dynamic
components,
I
suspect
will
also
have
the
same
thing
at
some
point
enabled
to
like
you
know.
This
is
like
equivalent
of
count
with
terraform,
for
us
count
doesn't
make
sense,
but
enabled
would,
if
we
have
that,
eventually
you
know
it's
reserved
for
now
and
then
health
and
debug.
These
are
fields
which
will
be
exposed
to
the
user
when
they
ask
for,
like
the
config
being
marshaled,
they'll
say
what
the
health
is
and
what
debug
info
is.
B
B
That
means,
for
example,
like
you,
don't
have
to
validate
if,
if
a
log
level
is
correct,
because
the
log
level
can
implement
this
interface-
and
you
can
just
force
that,
like
the
strings,
are
a
correct
value
and
if,
for
example,
if
if
it
was
log
level
and
the
only
about
log
levels
were
info
error,
whatever
those
and
you
put
in
fubar
you'd
get
back
an
hcl
error
saying
like
foobar
is
not
valid,
and
then
you
get
the
line
number
in
your
hcl
and
like
where
exactly
that's
wrong.
B
You
have
the
capsule
types
have
to
be
struck,
so
they
can't
be
interfaces,
but
it
can
be
a
struct
that
contains
an
interface
so
that
that,
like
effectively
is
mostly
the
same
thing.
You
have
to
wrap
it.
Then
you
have
to
register
components
by
calling
the
register
method.
So
the
interface
of
components
are
really
minimal.
They
just
have
to
run
is
which
is
guaranteed
to
be
called
if
the
component
was,
if
the
component
was
built
correctly,
it's
guaranteed
to
be
called
exactly
once
per
component.
B
B
Like
a
fatal
error,
then
update
would
be
called
any
time.
The
inputs
or
the
arguments
for
the
component
gets
reevaluated
and
you
would
be
given
the
the
the
new
set
of
arguments
and
you
should
change
your
state
to
match
what
those
are.
B
Also
components
can
implement
the
health
component
interface,
so
this
is
if
they
have
health
information
to
export.
So
if
they
do
have
the
health
information,
this
might
be
called
whenever
the
user
is
requesting
health
for
components
or
like.
If
we
have
like
a
metrics
exporter
which
shows
health,
whatever
it
might
be
called
at
any
time
might
be
called
synchronous,
asynchronously
multiple
go
routines.
It
should
be
go
routine,
safe.
B
The
health
struct
is
a
tuple
of
state,
a
message
and
when
that
health
was
generated
so,
for
example,.
B
If
you
load
like
an
invalid
file,
it'll
get
marked
as
unhealthy
with
the
message
being
like
what
the
error
was
in
the
file
and
then
the
update
time
will
be
the
title.
The
time
you
tried
to
load
that
file,
but
then
components
can
have
whatever
you
know,
health
they
want.
So
the
health
types
are
unknown.
This
is
like
the
initial
state
and
then
they
could
either
be
healthy
or
unhealthy
and
the
controller
can
mark
them
as
exited
if
the
run
method
exited
before
it
should
have
any
questions
so
far,.
B
I'm
gonna
skip
over
register
ghost
struct,
it's
just
basically
what
I
said
you
can
read
the
documentation
for
that
in
the
registry.
When
you
register
in
a
component,
you
have
to
give
it
a
name
which
is
like
remote.http,
remote.vault
or
whatever.
There's
some
rules
here
you
can.
You
can
read
that
in
detail.
If
you
want
the
components
which
have
to
be
globally
unique,
are
called
singletons,
so
like
node
exporter
would
be
a
singleton
and
you
would
set
that
to
true,
and
then
you
have
to
register
what
your
types
are.
B
All
right
last
bit
is
build.
This
is
how
we
build
new
components,
so
we
give
you
a
set
of
global
options,
which
are
things
like.
What's
your
id
and
what
logger
can
you
use
and
where
should
you
write
data,
then
here's
the
function
to
call
if
you,
if
you
change
your
exports,
then
the
the
initial
set
of
arguments
that
got
evaluated
and
then
arguments
past
that
will
be
called
through
the
the
update
method.
B
I
think
the
rest
of
this
is
self-explanatory.
Like
oh
right,
then
this
is
internal.
We
need
to
build
a
schema
for,
like
all
the
components
that
are
registered.
So
if
you
call
this,
this
is
used
by
the
controller
itself.
Users,
wouldn't
developers,
wouldn't
really
use
this
directly.
B
All
right,
I
have
an
all
component
here.
It
doesn't
do
anything,
but
the
idea
is,
you
would
import
all
components
that
exist
and
then,
if
someone
wanted
everything
they
could
just
import
this
package
instead
of
all
like
20
or
however
many
we
have
excuse
me
all
right.
Moving
on
to
the
the
flow
package
itself.
B
Okay,
a
lot
of
here-
a
lot
of
this
I
already
described,
but
what
I?
What
I
do
want
to
add
is
the
the
overall
health
of
a
component
is
merged
with
the
the
health
of
the
component
at
a
graph
level.
So
a
component
which
is
running
could
be
could
be
healthy.
B
However,
it
could
be
unhealthy
from
a
graph
perspective
because
we
tried
to
reevaluate
its
input
and
something
failed
or
like
the
revaluate
input
was
wrong
for
some
reason.
The
component
itself
wouldn't
know
that,
because
its
update
method
never
got
called,
but
we
would
know
that
at
the
graph
level.
So
if,
at
a
graph
level
the
node
is
unhealthy,
we
override
what
the
component
says
and
we'll
report
kind
of
like
the
graph
level
health.
B
I
document
rules
for
how
that
merging
is
done
in
in
the
component,
node
struct
and
then
evaluating.
I
think
I
already
talked
about
this,
like
you
have
to
evaluate
things
with
no
dependencies
first
before
you
can
evaluate
anything
else
and
you
can't
have
cyclic
dependencies.
B
Oh
right,
the
other
part
we
do
not
propagate
errors.
So
if
a
component
tries
to
be
reevaluated
and
it
fails,
it'll
be
left
in
its
last
known
state,
so
any
component
referencing
that
component
will
still
like
be
referencing
its
last
valid
state.
That
means,
for
example,
if
your
api
key
is
coming
from
vault
and
for
whatever
reason,
vault
breaks
or
vault
goes
down,
we're
still
using
the
last
valid
api.
Key
and
metrics
are
still
being
sent.
B
So,
like
one
thing,
breaking
isn't
gonna
make
all
your
your
entire
agent
just
stop
working,
but
it
does,
but
it
also
means,
like
the
declarative
nature
of
the
little,
maybe
not
completely
true,
it's
more
like.
Well,
no,
it's
still
true,
because
the
the
the
running
component
is
still
in
its
last
valid
state.
It's
just
it
can't
update.
A
For
the
exports
are
we
going
to?
Is
the
pattern
to
have
them?
You
know,
because
we
can
essentially
pass
pointers
around
that.
Another
component
should
not
update
anything
in
those
exports
and
it's
simply
enforced
by
developer
convention.
B
Yes,
I
think
I
think
yeah,
like
maybe
under
really
weird
circumstances.
You
might
want
to
have
a
ghost
struct,
which
expects
to
be
overwritten
but
that'll
be
up
to
the
documentation
of
the
type
you're
exposing
so
like
for,
like,
like
with
the
with
the
other
example
I
was
showing
with
like
the
metrics
receiver
and
stuff.
B
A
Yeah,
I
guess
you
could
definitely
see
instances
where
you
would
add
to
a
queue
or
some
sort
of
data
structure.
You
know
for
for
some
sort
of
processing,
but
not
override
the
data
structure
itself.
Yeah.
B
B
Okay,
so
that's
all
that
I
don't
know
if
I
want
to
dive
in
too
much
into
the
detail.
It's
kind
of
one
touch
just
at
a
high
level
about
what's
going
on
here,
so
I
I've
opted
for
internal
packages
for
this
one,
so
we
can
kind
of
have
like
a
little
bit
cleaner
api
at
the
top
level
than
weird
low
level
apis
at
the
low
level.
The
top
level
flow
package
does
very
little.
It
just
creates
an
update
queue,
a
scheduler
and
a
loader,
and
then
it
wires
those
three
things
together.
B
So
when,
for
example,
the
loader
it'll
say
like
this
component
changed,
if
that,
if
that
gets
called,
we
immediately
put
it
in
the
queue
and
then
in
a
go
routine.
What
we're
running
the
controller
we
try
dequeueing
from
that
queue
and
then,
if
we
get
an
element,
we
will
reevaluate
that
thing
and
all
of
its
dependencies.
B
Otherwise,
if
like
we
just
did
a
load,
we
have
new
components,
we'll
pass
those
over
to
the
to
the
scheduler
for
running.
So
this
is
really
just
the
glue
code
of
all
the
of
all
the
underlying
parts.
B
I
do
want
to
show
test
components.
I
wrote
actually
now
before
I
do
that,
so
the
root
context,
I
copied
all
of
the
functions
that
terraform
was
using,
but
then
I
changed
the
naming
convention
to
snake
case,
because
I
think
these
are
more
useful
or
more
readable
than
like
this,
for
example,
which
is
what
terraform
did
one
exception.
B
Terraform
uses
like
an
index
function,
which
is
different
than
cty's
index
function,
and
I'm
I
just
didn't,
do
like
bring
it
over
yet,
but
we'd
want
to
probably
match
their
implementation
of
it,
and
then
I
implemented
one
example:
function
which
is
n
to
get
an
environment
variable.
So
I'll
show
you
how
that
works.
It's
it's
kind
of
gross.
It's
like
a
cty
function,
so
I
have.
We
have
one
parameter,
which
is
a
the
var
name
and
that
takes
a
string.
B
Then
we
output,
a
string
as
response
and
the
implication
just
like
gets
that
value
and
then
returns
it
back
as
a
cty
value.
We'd
probably
want
to
make
these
as
minimal
as
possible,
because
probably
looking
at
this
you're
like
oh,
that's,
not
very
pretty
so
it
would
be
possible
to
have
these.
Like
just
like
a
shim
around
like
an
actual
function,
kind
of
like
how
I'm
doing
it
here
with
being
a
shim
around
the
get
inve
getting
thing.
B
Okay,
I
don't
even
know
how
these
functions
do
I
just
I
just
imported
the
list
like
there's.
Apparently
you
can
do
a
csv
decode,
that's
interesting.
We
can
look
at
these
later,
but
I
don't
think
there's
I
mean
we
can
also
take
them
out
if
there's
something
we
don't
want
here,
but
I
think
most
of
these
are
probably
pretty
useful.
B
Okay,
then
the
config
file
allows
you
to
parse
an
htl
thing,
ignoring
implementation.
Here
you
get
back
this
file,
which
really
doesn't
have
anything
at
the
moment.
It's
just
like
the
name
of
the
file,
the
raw
hcl
file,
which
you
might
need,
and
then
the
list
of
components
to
load.
B
Okay,
all
right,
I
think,
yeah,
that's
everything
so
showing
one
of
the
tests,
I'm
using
some
tests
here
to
like
kind
of
just
validate
things
end
to
end.
So
here's
where
my
test
components
come
into
play.
I
have
two
of
them.
I
have
a
tick
test
component
which
will
emit
something
on
a
frequency
it'll
emit
the
current
time
on
a
frequency,
so
this
will
emit
the
current
time
every
one
second,
and
then
I
have
a
pass-through
component
which
anything
any
string
is
given
as
output
will
be
re-given
as
output.
B
So
this
is
a
really
weird
example,
but
every
one
second
we're
getting
the
current
time
and
then
we're
also,
you
know
passing
through
hello
world
and
then
here
we
pass
through
the
ticker
where,
like
it,
you
know
this
will
be
reevaluated
anytime.
The
tick
changes
so
it'll
be
it'll
re-expose
the
current
time
every
second,
and
then
this
will
just
oh
right,
and
then
this
passes
through
what
this
is
passing
through.
So
it's
like
a
chain.
B
This
should
demonstrate
that
kind
of
the
binding
of
values
works
across
multiple
components
and
that's
what
I'm
testing
here.
B
All
right,
the
implication
of
those
is
pretty
simple:
I'm
registering
them
with
the
name
and,
like
you
know
their
types,
I'm
calling
it
pastor
config
here.
This
should
probably
change.
This
probably
changed
arguments,
but
for
now
which
is
called
config
and
it
doesn't
do
anything
when
it
runs
because,
like
it's,
it's
never
gonna
like
do
anything
in
the
background.
It's
just
like
any
time.
It
gets
updated.
B
B
Okay,
then
the
pick
test
component-
this
actually
does
do
something
in
run
so
it'll
it'll
like
wait
for
the
next
tick
period
and
then,
whenever
it
does,
that
it'll
it'll
emit
the
current
time
at
the
tick
frequency.
So
we
call
this
just
in
case
the
frequency
changes
in
between
ticks,
so
when,
when
it
updates
we'll
store
that
new
frequency
and
we
reject
it
if
it's
zero,
oh
there's
a
bug
here.
B
The
bug
being
here
means
that
this
isn't
tested
very
well.
Is
that
wrong?
Oh
yeah!
That's
that's
not
right!
Okay,
so
I
guess
this
isn't
being
tested
right
now,
and
it
needs
to
be
all
right.
B
I
don't
know,
I
think
I
think
I
described
all
the
like
the
various
things
here
like
the
component-
I
guess
I'll
generally
say
what's
going
on
here.
B
So
when
we
create
a
component,
we
give
it
options
for
that
component,
which
are
like
a
shared
logger,
shared
data
directory
and
then
like
shared
function,
callback
function,
and
then
we
give
it
like
its
initial
hcl
block
at
this
point
like
we
don't
evaluate
it
because
we
don't
know
what
it
depends
on
yet
so
when
it
needs
to
be
evaluated,
you
can
call
this
evaluate
function
which
will
decode,
you
know
from
hcl
into
like
the
actual
go
type,
and
then
we
haven't
built
the
actual
component.
B
Yet
this
is
the
time
to
do
it.
Otherwise
we
just
update
the
existing
one
and
then
we'll
internally
store
arguments.
So
this
exposes
an
interface
to
the
controller
where
at
any
time
the
controller
can
ask
hey.
What
is
your
current
like
evaluated
arguments
and
we
can
return
that,
and
this
won't
be
updated
if
it
fails.
Obviously,
and
then
what
is
your
current
exports,
so
this
will
be
updated
anytime.
That
component
exposes
new
exports,
which
you
can
see
happen
here,
so
the
component
options
it's
on
state
change.
B
It
points
at
our
kind
of
set
export
method
which
will
make
sure
that
the
export
tape
hasn't
changed
and
then
internally
set
it
and
then
inform
the
controller
that
hey
this
component
just
changed.
You
should
you
should
cue
us
for
for
processing
current
health
right.
Okay,
this
is
the
last
this
last
bit.
I
think
I'll
probably
go
over
since
we're
40
minutes
yeah.
B
So
there's
a
precedent
here:
we're
tracking
two
internal
health
states
for
the
component,
we're
tracking
the
like
the
health
of
the
last
call
to
evaluate,
and
then
the
health
of
running
the
actual
component
so
overall
like
if
the
run
exited
that
is
like
the
highest
precedence,
unhealth
status
to
show
user
like
hey
it
doesn't
matter.
If
this
component
is
working
or
not,
you
should
know
like
it's
not
even
running
right.
Now.
That's
important,
then,
below
that,
if
the
evaluate
failed,
that's
also
really
important
to
say
to
the
user,
but
then
below
that
like.
B
If
the
component
has
its
own
health,
we
just
give
you
that,
but
if
it
doesn't
we'll
kind
of
fall
back
to
whatever,
like
the
most
recent
health
from
either
the
run
or
evaluate
method
was
so
that's
all
that,
like
this
is
doing
here,
it's
it's
kind
of
heavily
commented,
but
should
be
followable
after
kind
of
reading
that
precedence
order.
B
All
right-
and
then
I
think
I
I
really
oh-
I'm
not
going
to
go
into
that.
I
think
that
should
be
enough
for
for
readers
who
want
to
like
follow
through,
like
here's,
how
we
get
the
references
of
what
a
component
is
referencing
and
here's
the
implication
of
loader,
which
can
you
know,
apply
a
new
set
of
hdl
blocks
into
into
like
what's
being
loaded
and
give
you
know,
you
know,
evaluate
the
graph
and
re-evaluate
a
single
component
or
whatever,
then
the
q
and
scheduler
and
value
cache.
B
I
think
that's
kind
of
all
I
want
to
describe.
I
do
want
to
show
that
the
value
cache
is
actually
really
complicated.
We
have
to
like
recursively
build
so
ima.
Imagine
like
this
hdl
config
file
with
like
foo
something's,
true
bar
whatever
the
expectation
from
like
an
hcl
eval
context,
is
that
you
have
something
like
this.
Where,
like
you,
you
turn
it
into
like
a
giant
json
object.
B
So
we
do
that
recursively
and
you
can
follow
the
implementation
here
for
how
that's
being
done,
but
it's
probably
like
the
the
most
weirdly
complicated
part
of
all
the
code,
and
we
have.
We
have
a
good
test
for
it
that
kind
of
shows
that
that's
actually
happening
underneath
the
hood
yeah.
So
we
expect
we
can't
just
test
one
giant
object,
because
we
have
to
have
one
variable
per
top
level
key,
but
this
is
showing
that
the
constructed
foo
matches
this
cty
object
and
the
expected
bar
matches.
B
The
cty
object
also
that
that's
a
shouldn't
have
the
parentheses
there.
Okay,
I'm
not
showing
the
dag.
I
think
most
people
here
know
what
a
graph
is
and
they
can
kind
of
follow
the
implementation.
Nothing
special
is
going
on
and
we
showed
everything
else
anything
someone
wants
to
look
at
kind
of,
or
do
you
kind
of
want
to
move
to
like
discussion
or
any
questions.
B
Okay,
thank
you.
Hopefully
that
was
helpful.
A
That
was
super
awesome
and
looking
over
it
probably
today
and
maybe
write
some
components
and
see
how
things
hook
up.
B
A
That's
what
you
find
when
you
do
a
public
review
right.
B
A
Then
yeah
we
can
get
people
back
a
little
bit
time
and
we'll
meet
again
in
roughly
a
month.