Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add remote configuration worker #2691

Merged
merged 5 commits into from
Mar 21, 2023
Merged

Conversation

lloeki
Copy link
Member

@lloeki lloeki commented Mar 14, 2023

What does this PR do?

Implement a polling worker for remote configuration.

Motivation

Remote configuration

Additional Notes

This is a simple generic polling worker:

  • pass it a block via new and it'll call it every interval
  • it can be stopped and started in a thread safe way

There is no fork protection: it is supposed to start on demand when the first request comes in.

How to test the change?

Example to use it in conjunction with the remote configuration client is below.

Note that the agent may not reply immediately with a full configuration, but it happens eventually.

  require 'ddtrace'

  Datadog.configure do |c|
    c.agent.host = '192.168.135.133'
    #c.tracing.enabled = true
    #c.diagnostics.debug = true
  end

  transport_options = {
    agent_settings: Datadog::Core::Configuration::AgentSettingsResolver.call(
      Datadog.configuration
    )
  }

  require 'datadog/core/transport/http'

  transport_v7 = Datadog::Core::Transport::HTTP.v7(**transport_options.dup)

  require 'datadog/core/remote/client'

  client = Datadog::Core::Remote::Client.new(transport_v7)
  repository = client.instance_eval { @repository }
  
  require 'datadog/core/remote/worker'
  
  worker = Datadog::Core::Remote::Worker.new(interval: 10) do
    client.sync

    puts '========='
    pp repository
    puts '========='
  end

  worker.start
  sleep 100
  worker.stop
  
  repository.contents

@github-actions github-actions bot added the core Involves Datadog core libraries label Mar 14, 2023
@lloeki
Copy link
Member Author

lloeki commented Mar 14, 2023

Pending:

  • specs
  • RBS typing

@lloeki lloeki force-pushed the add-remote-config-client branch from e6e6425 to 6d0e56b Compare March 16, 2023 11:01
@lloeki lloeki force-pushed the add-remote-config-worker branch from 08eff6e to cc025a9 Compare March 16, 2023 11:12
@lloeki
Copy link
Member Author

lloeki commented Mar 16, 2023

Rebased using git rebase --onto add-remote-config-client 08eff6e^ add-remote-config-worker

@lloeki lloeki force-pushed the add-remote-config-client branch from 6d0e56b to 175e9bd Compare March 16, 2023 12:54
@lloeki lloeki force-pushed the add-remote-config-worker branch from cc025a9 to 59f4de9 Compare March 16, 2023 12:56
@lloeki
Copy link
Member Author

lloeki commented Mar 16, 2023

Rebased using git rebase --onto add-remote-config-client cc025a9^ add-remote-config-worker

@GustavoCaso GustavoCaso force-pushed the add-remote-config-client branch 4 times, most recently from db9c31e to 5220533 Compare March 17, 2023 14:37
@lloeki lloeki force-pushed the add-remote-config-worker branch from 59f4de9 to 39ec14e Compare March 20, 2023 15:40
Base automatically changed from add-remote-config-client to master March 21, 2023 09:24
@GustavoCaso GustavoCaso force-pushed the add-remote-config-worker branch from 39ec14e to 42b74f7 Compare March 21, 2023 10:05
@GustavoCaso
Copy link
Member

Rebased using git rebase master

Copy link
Member Author

@lloeki lloeki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a few things could be improved

sig/datadog/core/remote/worker.rbs Outdated Show resolved Hide resolved
spec/datadog/core/remote/worker_spec.rb Show resolved Hide resolved
spec/datadog/core/remote/worker_spec.rb Outdated Show resolved Hide resolved
spec/datadog/core/remote/worker_spec.rb Outdated Show resolved Hide resolved
spec/spec_helper.rb Outdated Show resolved Hide resolved
@GustavoCaso GustavoCaso force-pushed the add-remote-config-worker branch from a6d21d2 to 748ee58 Compare March 21, 2023 13:23
@GustavoCaso GustavoCaso marked this pull request as ready for review March 21, 2023 13:24
@GustavoCaso GustavoCaso requested a review from a team March 21, 2023 13:24
Comment on lines +28 to +29
expect(worker).to receive(:acquire_lock).at_least(:once)
expect(worker).to receive(:release_lock).at_least(:once)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at_least(:once) because calling worker.stop, which happen on the after block, will also call acquire_lock && release_lock

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider perhaps making the mutex a dependency that can be injected (via the constructor) to avoid having to set expectations on the class being tested.

Something along the lines of

      class Worker
        def initialize(interval:, mutex: Mutex.new, &block)
          @mutex = mutex

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it that way before.

I don't mind having to set expectations for the class being tested. Especially if the API does not break, if in the future we use a different class than mutex, we could change the underlaying lock mechanism without having to change the class initialise arguments or test.

Copy link
Member

@ivoanjo ivoanjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few notes, nothing blocking! :)

Comment on lines +78 to +86
def poll(interval)
loop do
break unless @mutex.synchronize { @starting || @started }

call

sleep(interval)
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Since this runs on a background thread, you may want to log if it exits with an exception


@starting = true

@thr = Thread.new { poll(@interval) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Consider naming this thread (on Ruby 2.3+) -- this will show up in the profiler clearly, as well as in other debugging tools

Comment on lines +28 to +29
expect(worker).to receive(:acquire_lock).at_least(:once)
expect(worker).to receive(:release_lock).at_least(:once)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider perhaps making the mutex a dependency that can be injected (via the constructor) to avoid having to set expectations on the class being tested.

Something along the lines of

      class Worker
        def initialize(interval:, mutex: Mutex.new, &block)
          @mutex = mutex

Comment on lines +44 to +49
it 'runs block' do
worker.start
# Wait for the work task to execute once
queue.pop
expect(result).to eq([1])
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Having both queue and result seems a bit redundant -- consider maybe using expect(queue.pop).to be 1

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. Will make sure to change it in a follow up PR

@GustavoCaso
Copy link
Member

GustavoCaso commented Mar 21, 2023

@ivoanjo Thanks for all the suggestions. I'm going to go ahead and merge it, but I will get back to those in a follow-up PR 😄

@GustavoCaso GustavoCaso merged commit c8f02ef into master Mar 21, 2023
@GustavoCaso GustavoCaso deleted the add-remote-config-worker branch March 21, 2023 16:11
@github-actions github-actions bot added this to the 1.11.0 milestone Mar 21, 2023
@ivoanjo
Copy link
Member

ivoanjo commented Mar 21, 2023

Yup, sounds good :)

@lloeki lloeki modified the milestones: 1.11.0, 1.11.0.beta1 Apr 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Involves Datadog core libraries
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants