diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..6b8710a7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +.git diff --git a/.ruby-version b/.ruby-version index d48d3702..ef538c28 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.6.9 +3.1.2 diff --git a/Gemfile b/Gemfile index ba0fa955..3d1c8662 100644 --- a/Gemfile +++ b/Gemfile @@ -10,7 +10,7 @@ gem 'bundler', File.read(File.join(__dir__, '.bundler-version')).strip # Dependencies for connectors gem 'activesupport', '~>5.2.6' -gem 'mime-types', '= 3.1' +gem 'mime-types', '~> 3.3' gem 'tzinfo-data' gem 'tzinfo' gem 'fugit', '~> 1.5.3' @@ -26,6 +26,8 @@ gem 'dry-inflector', '= 0.2.1' gem 'dry-schema', '= 1.8.0' gem 'dry-validation', '= 1.7.0' +gem 'rack', '>= 2.2.3.1' + group :test do gem 'rspec-collection_matchers', '~> 1.2.0' gem 'rspec-core', '~> 3.10.1' @@ -34,9 +36,8 @@ group :test do gem 'rubocop-performance', '1.11.5' gem 'rspec-mocks' gem 'webmock' - gem 'rack', '>= 2.2.3.1' gem 'rack-test' - gem 'ruby-debug-ide' + # gem 'ruby-debug-ide' gem 'pry-remote' gem 'pry-nav' gem 'debase', '0.2.5.beta2' diff --git a/Gemfile.lock b/Gemfile.lock index ea0ed83b..bd5cf076 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -105,7 +105,7 @@ GEM concurrent-ruby (~> 1.0) jwt (2.3.0) method_source (1.0.0) - mime-types (3.1) + mime-types (3.4.1) mime-types-data (~> 3.2015) mime-types-data (3.2022.0105) minitest (5.16.1) @@ -134,7 +134,6 @@ GEM rack-test (1.1.0) rack (>= 1.0, < 3) rainbow (3.1.1) - rake (13.0.6) regexp_parser (2.2.1) remedy (0.3.0) rexml (3.2.5) @@ -165,8 +164,6 @@ GEM rubocop-performance (1.11.5) rubocop (>= 1.7.0, < 2.0) rubocop-ast (>= 0.4.0) - ruby-debug-ide (0.7.3) - rake (>= 0.8.1) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) signet (0.16.0) @@ -226,7 +223,7 @@ DEPENDENCIES fugit (~> 1.5.3) hashie (~> 5.0.0) httpclient (~> 2.8.3) - mime-types (= 3.1) + mime-types (~> 3.3) mongo (~> 2.18) pry-nav pry-remote @@ -239,7 +236,6 @@ DEPENDENCIES rspec_junit_formatter rubocop (= 1.18.4) rubocop-performance (= 1.11.5) - ruby-debug-ide signet (~> 0.16.0) simplecov simplecov-material @@ -249,7 +245,7 @@ DEPENDENCIES webmock RUBY VERSION - ruby 2.6.9p207 + ruby 3.1.2p20 BUNDLED WITH 2.3.15 diff --git a/Makefile b/Makefile index 83e96c6c..843d5478 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,10 @@ install: - gem install bundler -v $(shell cat .bundler-version) && rbenv rehash bundle _$(shell cat .bundler-version)_ install --jobs 1 +install_for_production: + - gem install bundler -v $(shell cat .bundler-version) && rbenv rehash + bundle _$(shell cat .bundler-version)_ install --without development test --jobs 1 + build-docker: docker build -t connectors . @@ -80,6 +84,12 @@ run-docker: exec_app: cd lib/app; bundle _$(shell cat .bundler-version)_ exec ruby app.rb +run_producer: + cd lib/app; bundle _$(shell cat .bundler-version)_ exec ruby producer_app.rb + +run_consumers: + cd lib/app; bundle _$(shell cat .bundler-version)_ exec ruby consumer_app.rb + exec_cli: cd lib/app; bundle _$(shell cat .bundler-version)_ exec ruby console_app.rb diff --git a/k8s/Dockerfile b/k8s/Dockerfile new file mode 100644 index 00000000..aa3b6255 --- /dev/null +++ b/k8s/Dockerfile @@ -0,0 +1,29 @@ +FROM ubuntu:focal + +# installing all system dependencies, yq, ruby-build and rbenv +RUN apt-get update && \ + apt-get install --yes --no-install-recommends uuid-runtime curl ca-certificates git make build-essential libssl-dev libreadline-dev zlib1g-dev && \ + rm -rf /var/lib/apt/lists/* && \ + curl -L https://github.com/mikefarah/yq/releases/download/v4.24.2/yq_linux_amd64.tar.gz | tar -xzvf - && mv yq_linux_amd64 /usr/bin/yq && \ + git clone https://github.com/rbenv/rbenv.git ~/.rbenv && \ + curl -L https://github.com/sstephenson/ruby-build/archive/v20220324.tar.gz | tar -zxvf - -C /tmp/ && \ + cd /tmp/ruby-build-* && ./install.sh + +# set the env +ENV PATH /root/.rbenv/bin:/root/.rbenv/shims:$PATH +ENV RUBY_VERSION 2.6.9 +RUN echo 'eval "$(rbenv init -)"' >> .bashrc +RUN echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh # or /etc/profile + +RUN RUBY_CONFIGURE_OPTS=--disable-install-doc rbenv install 2.6.9 + +ENV ENT_SEARCH_CONFIG_PATH /app/k8s/stackpack/config/enterprise_search.yml +ENV CONNECTORS_CONFIG /app/config/connectors.yml + +WORKDIR /app +COPY . /app + +# run the make file to install the app +RUN make install_for_production + +CMD ["make", "exec_app"] diff --git a/k8s/Makefile b/k8s/Makefile new file mode 100644 index 00000000..34dcc567 --- /dev/null +++ b/k8s/Makefile @@ -0,0 +1,10 @@ +CURDIR = $(shell pwd) + + build: + docker build -t docker.elastic.co/enterprise-search/connectors-python . + + run: + docker run --name connectors_python --rm -v $(CURDIR)/stackpack:/app docker.elastic.co/enterprise-search/connectors-python + + shell: + docker exec -u root -it connectors_python /bin/bash diff --git a/k8s/configmaps/connectors-python.yml b/k8s/configmaps/connectors-python.yml new file mode 100644 index 00000000..50935c14 --- /dev/null +++ b/k8s/configmaps/connectors-python.yml @@ -0,0 +1,32 @@ +elasticsearch: + host: http://host.docker.internal:9200 + username: elastic + password: changeme + ssl: true + bulk_queue_max_size: 1024 + bulk_display_every: 100 + bulk_chunk_size: 150 + request_timeout: 120 + max_wait_duration: 120 + initial_backoff_duration: 1 + backoff_multiplier: 2 + log_level: info + +service: + idling: 30 + heartbeat: 300 + max_errors: 20 + max_errors_span: 600 + trace_mem: false + +native_service_types: + - mysql + + # some id + #connector_id: '1' + +sources: + mongodb: connectors.sources.mongo:MongoDataSource + s3: connectors.sources.aws:S3DataSource + dir: connectors.sources.directory:DirectoryDataSource + mysql: connectors.sources.mysql:MySqlDataSource diff --git a/k8s/configmaps/connectors.yml b/k8s/configmaps/connectors.yml new file mode 100644 index 00000000..74b88676 --- /dev/null +++ b/k8s/configmaps/connectors.yml @@ -0,0 +1,25 @@ +# general metadata +version: "8.6.0.0-20221123T101025Z" +repository: "git@github.com:elastic/connectors.git" +revision: "5452054864ad0863e9b185d25b28f1ff2f214849" +elasticsearch: + # cloud_id: CHANGEME + hosts: http://localhost:9200 + api_key: ZTdpTmhZUUJFMXlUVTl1eUcyTks6UTVwdDBaVlBSSXVCM2doMWFxMlYtQQ== + retry_on_failure: 3 + request_timeout: 120 + disable_warnings: true + trace: false + log: false +thread_pool: + min_threads: 0 + max_threads: 5 + max_queue: 100 +log_level: info +ecs_logging: false +poll_interval: 3 +termination_timeout: 60 +heartbeat_interval: 1800 +native_mode: true +connector_id: CHANGEME +service_type: CHANGEME diff --git a/k8s/configmaps/enterprise_search.yml b/k8s/configmaps/enterprise_search.yml new file mode 100644 index 00000000..b486a010 --- /dev/null +++ b/k8s/configmaps/enterprise_search.yml @@ -0,0 +1,13 @@ +ent_search: + listen_host: 0.0.0.0 + ssl: + enabled: false + +elasticsearch: + # host: http://0.0.0.0:9200 + host: http://host.docker.internal:9200 + username: elastic + password: changeme + +allow_es_settings_modification: true +secret_management.encryption_keys: [1603f8d7f94483625f252111ba7b4d10049a9c13bc4d4838ea2039516f6f1493] diff --git a/k8s/configmaps/kustomization.yml b/k8s/configmaps/kustomization.yml new file mode 100644 index 00000000..b619f267 --- /dev/null +++ b/k8s/configmaps/kustomization.yml @@ -0,0 +1,8 @@ +--- +configMapGenerator: +- name: enterprise-search-python-connectors-configuration + files: + - connectors-python.yml +- name: enterprise-search-configuration + files: + - enterprise_search.yml diff --git a/k8s/deployment.yml b/k8s/deployment.yml new file mode 100644 index 00000000..fe1aef5c --- /dev/null +++ b/k8s/deployment.yml @@ -0,0 +1,121 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: connectors-ruby-producer + labels: + service.type: connectors-ruby + service.group: producer +spec: + replicas: 1 + selector: + matchLabels: + service.type: connectors-ruby + service.group: producer + template: + metadata: + labels: + service.type: connectors-ruby + service.group: producer + spec: + containers: + - name: connectors-ruby + image: connectors:latest + command: ["make"] + args: ["run_producer"] + imagePullPolicy: Never + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: connectors-ruby-consumer + labels: + service.type: ruby + service.group: consumer +spec: + replicas: 1 + selector: + matchLabels: + service.type: connectors-ruby + service.group: consumer + template: + metadata: + labels: + service.type: connectors-ruby + service.group: consumer + spec: + containers: + - name: connectors-ruby + imagePullPolicy: Never + image: connectors:latest + command: ["make"] + args: ["run_consumers"] + volumeMounts: + - name: enterprise-search-configuration + mountPath: /app/config/ent-search + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + imagePullPolicy: Never + volumes: + - name: enterprise-search-configuration + configMap: + name: enterprise-search-configuration-4bf99k7m9b +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: connectors-python + labels: + app: python + group: default +spec: + replicas: 1 + selector: + matchLabels: + service.type: connectors-python + service.group: default + template: + metadata: + labels: + service.type: connectors-python + service.group: default + spec: + containers: + - name: connectors-python + image: connectors-python:latest + command: ["elastic-ingest"] + args: ["-c", "/app/config/connectors/connectors-python.yml", "--filebeat", '--debug'] + env: + - name: ENT_SEARCH_CONFIG_PATH + value: /app/config/ent-search/enterprise_search.yml + volumeMounts: + - name: enterprise-search-configuration + mountPath: /app/config/ent-search/ + - name: enterprise-search-python-connectors-configuration + mountPath: /app/config/connectors/ + imagePullPolicy: Never + resources: + requests: + memory: "128Mi" + cpu: "250m" + limits: + memory: "256Mi" + cpu: "500m" + volumes: + - name: enterprise-search-configuration + configMap: + name: enterprise-search-configuration-4bf99k7m9b + - name: enterprise-search-python-connectors-configuration + configMap: + name: enterprise-search-python-connectors-configuration-5gdd5tk82b diff --git a/k8s/hpa.yml b/k8s/hpa.yml new file mode 100644 index 00000000..f95b29a3 --- /dev/null +++ b/k8s/hpa.yml @@ -0,0 +1,13 @@ +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: hpa-connectors-ruby-consumer +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: connectors-ruby-consumer + minReplicas: 1 + maxReplicas: 5 + targetCPUUtilizationPercentage: 30 + diff --git a/k8s/namespace.yml b/k8s/namespace.yml new file mode 100644 index 00000000..cc49ec0b --- /dev/null +++ b/k8s/namespace.yml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: enterprise-search + labels: + name: enterprise-search diff --git a/k8s/stackpack/config/supervisord.conf b/k8s/stackpack/config/supervisord.conf new file mode 100644 index 00000000..29c41925 --- /dev/null +++ b/k8s/stackpack/config/supervisord.conf @@ -0,0 +1,39 @@ +[supervisord] +# runs in the foreground as the Docker main process. +nodaemon=true + +# redirecting all logs to the main process stderr/stdout +logfile=/dev/stdout +logfile_maxbytes=0 + +loglevel=info +pidfile=/app/tmp/supervisord.pid +minfds=1024 +minprocs=200 +childlogdir=/app/tmp/ +stdout_events_enabled = true +stderr_events_enabled = true + +# kubernetes should map enterprise_search.yml +environment=ENT_SEARCH_CONFIG_PATH=/app/k8s/stackpack/config/enterprise_search.yml,CONNECTORS_CONFIG=/app/config/connectors.yml + +[program:connectors-ruby] +command=make exec_app +priority=2 + +# needs to be up at least 30 seconds to be considered successful +startsecs=30 +autorestart=true +startretries=10000 +killasgroup=true + +stdout_logfile=/dev/stdout +stdout_capture_maxbytes=0 +stdout_logfile_maxbytes=0 +redirect_stderr=true + +# push things in `app-server` using the filebeat format +# stderr_logfile=/app/logs/app-server.log +# stdout_logfile=/app/logs/app-server.log +# stdout_logfile_backups=0 +# stderr_logfile_backups=0 diff --git a/lib/app/consumer.rb b/lib/app/consumer.rb new file mode 100644 index 00000000..5152ed73 --- /dev/null +++ b/lib/app/consumer.rb @@ -0,0 +1,75 @@ +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License; +# you may not use this file except in compliance with the Elastic License. +# + +# frozen_string_literal: true + +require 'active_support' +require 'concurrent' +require 'connectors' +require 'core' +require 'utility' +require 'app/config' + +module App + class Consumer + POLL_INTERVAL = (App::Config.poll_interval || 3).to_i + TERMINATION_TIMEOUT = (App::Config.termination_timeout || 60).to_i + HEARTBEAT_INTERVAL = (App::Config.heartbeat_interval || 60 * 30).to_i + MIN_THREADS = (App::Config.dig(:thread_pool, :min_threads) || 0).to_i + MAX_THREADS = (App::Config.dig(:thread_pool, :max_threads) || 5).to_i + MAX_QUEUE = (App::Config.dig(:thread_pool, :max_queue) || 100).to_i + JOB_CLEANUP_INTERVAL = (App::Config.job_cleanup_interval || 60 * 5).to_i + + @running = Concurrent::AtomicBoolean.new(false) + + class << self + def start! + Utility::Logger.info("Starting connector service in #{App::Config.native_mode ? 'native' : 'non-native'} mode...") + start_consumer! + end + + def shutdown! + Utility::Logger.info("Shutting down connector service...") + stop_consumer! + end + + private + + attr_reader :running + + + def scheduler + @scheduler ||= if App::Config.native_mode + Core::NativeScheduler.new(POLL_INTERVAL, HEARTBEAT_INTERVAL) + else + Core::SingleScheduler.new(App::Config.connector_id, POLL_INTERVAL, HEARTBEAT_INTERVAL) + end + end + + def start_consumer! + @consumer = Core::Jobs::Consumer.new( + poll_interval: POLL_INTERVAL, + termination_timeout: TERMINATION_TIMEOUT, + min_threads: MIN_THREADS, + max_threads: MAX_THREADS, + max_queue: MAX_QUEUE, + max_ingestion_queue_size: (App::Config.max_ingestion_queue_size || Utility::Constants::DEFAULT_MAX_INGESTION_QUEUE_SIZE).to_i, + max_ingestion_queue_bytes: (App::Config.max_ingestion_queue_bytes || Utility::Constants::DEFAULT_MAX_INGESTION_QUEUE_BYTES).to_i, + scheduler: scheduler + ) + + @consumer.subscribe!(index_name: Utility::Constants::JOB_INDEX) + end + + def stop_consumer! + return if @consumer.nil? + return unless @consumer.running? + + @consumer.shutdown! + end + end + end +end diff --git a/lib/app/consumer_app.rb b/lib/app/consumer_app.rb new file mode 100644 index 00000000..55fde8d3 --- /dev/null +++ b/lib/app/consumer_app.rb @@ -0,0 +1,30 @@ +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License; +# you may not use this file except in compliance with the Elastic License. +# + +# frozen_string_literal: true + +$LOAD_PATH << '../' + +require 'app/dispatcher' +require 'app/consumer' +require 'app/config' +require 'app/preflight_check' +require 'utility/environment' +require 'utility/logger' + +module App + Utility::Environment.set_execution_environment(App::Config) do + App::PreflightCheck.run! + + # set exit hook + Kernel.at_exit { App::Consumer.shutdown! } + + App::Consumer.start! + rescue App::PreflightCheck::CheckFailure => e + Utility::Logger.error("Preflight check failed: #{e.message}") + exit(-1) + end +end diff --git a/lib/app/producer.rb b/lib/app/producer.rb new file mode 100644 index 00000000..b1eb3bb2 --- /dev/null +++ b/lib/app/producer.rb @@ -0,0 +1,124 @@ +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License; +# you may not use this file except in compliance with the Elastic License. +# + +# frozen_string_literal: true + +require 'active_support/json' +require 'concurrent' +require 'connectors' +require 'core' +require 'utility' +require 'app/config' + +module App + class Producer + POLL_INTERVAL = (App::Config.poll_interval || 3).to_i + TERMINATION_TIMEOUT = (App::Config.termination_timeout || 60).to_i + HEARTBEAT_INTERVAL = (App::Config.heartbeat_interval || 60 * 30).to_i + MIN_THREADS = (App::Config.dig(:thread_pool, :min_threads) || 0).to_i + MAX_THREADS = (App::Config.dig(:thread_pool, :max_threads) || 5).to_i + MAX_QUEUE = (App::Config.dig(:thread_pool, :max_queue) || 100).to_i + JOB_CLEANUP_INTERVAL = (App::Config.job_cleanup_interval || 60 * 5).to_i + + @running = Concurrent::AtomicBoolean.new(false) + + class << self + def start! + running! + Utility::Logger.info("Producer in #{App::Config.native_mode ? 'native' : 'non-native'} mode...") + start_job_cleanup_task! + start_polling_jobs! + end + + def shutdown! + Utility::Logger.info("Shutting down connector service with pool [#{pool.class}]...") + running.make_false + job_cleanup_timer.shutdown + scheduler.shutdown + end + + private + + attr_reader :running + + def running! + raise 'connector service is already running!' unless running.make_true + end + + def scheduler + @scheduler ||= if App::Config.native_mode + Core::NativeScheduler.new(POLL_INTERVAL, HEARTBEAT_INTERVAL) + else + Core::SingleScheduler.new(App::Config.connector_id, POLL_INTERVAL, HEARTBEAT_INTERVAL) + end + end + + def job_cleanup_timer + @job_cleanup_timer ||= Concurrent::TimerTask.new(:execution_interval => JOB_CLEANUP_INTERVAL) do + connector_id = App::Config.native_mode ? nil : App::Config.connector_id + Core::JobCleanUp.execute(connector_id) + end + end + + def start_job_cleanup_task! + job_cleanup_timer.execute + end + + def start_polling_jobs! + scheduler.when_triggered do |connector_settings, task| + case task + when :sync + # TODO: #update_connector_sync_now should be moved to Core::ConnectorSettings, + # there should not be any business logic related code in Core::ElasticConnectorActions. + # #update_connector_sync_now should not update `last_synced` after https://github.com/elastic/enterprise-search-team/issues/3366 is resolved, + # schedule should not based on `last_synced` + Core::ElasticConnectorActions.update_connector_sync_now(connector_settings.id, false) + + Core::Jobs::Producer.enqueue_job(job_type: :sync, connector_settings: connector_settings) + when :heartbeat + start_heartbeat_task(connector_settings) + when :configuration + start_configuration_task(connector_settings) + when :filter_validation + start_filter_validation_task(connector_settings) + else + Utility::Logger.error("Unknown task type: #{task}. Skipping...") + end + end + rescue StandardError => e + Utility::ExceptionTracking.log_exception(e, 'The connector service failed due to unexpected error.') + end + + def start_heartbeat_task(connector_settings) + Utility::Logger.info("Sending heartbeat for #{connector_settings.formatted}...") + Core::Heartbeat.send(connector_settings) + rescue StandardError => e + Utility::ExceptionTracking.log_exception(e, "Heartbeat task for #{connector_settings.formatted} failed due to unexpected error.") + end + + def start_configuration_task(connector_settings) + Utility::Logger.info("Updating configuration for #{connector_settings.formatted}...") + # when in non-native mode, populate the service type if it's not in connector settings + service_type = if !App::Config.native_mode && connector_settings.needs_service_type? + App::Config.service_type + else + nil + end + Core::Configuration.update(connector_settings, service_type) + rescue StandardError => e + Utility::ExceptionTracking.log_exception(e, "Configuration task for #{connector_settings.formatted} failed due to unexpected error.") + end + + def start_filter_validation_task(connector_settings) + Utility::Logger.info("Validating filters for #{connector_settings.formatted}...") + validation_job_runner = Core::Filtering::ValidationJobRunner.new(connector_settings) + validation_job_runner.execute + rescue StandardError => e + Utility::ExceptionTracking.log_exception(e, "Filter validation task for #{connector_settings.formatted} failed due to unexpected error.") + end + end + end +end diff --git a/lib/app/producer_app.rb b/lib/app/producer_app.rb new file mode 100644 index 00000000..2e71c82d --- /dev/null +++ b/lib/app/producer_app.rb @@ -0,0 +1,30 @@ +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License; +# you may not use this file except in compliance with the Elastic License. +# + +# frozen_string_literal: true + +$LOAD_PATH << '../' + +require 'app/dispatcher' +require 'app/producer' +require 'app/config' +require 'app/preflight_check' +require 'utility/environment' +require 'utility/logger' + +module App + Utility::Environment.set_execution_environment(App::Config) do + App::PreflightCheck.run! + + # set exit hook + Kernel.at_exit { App::Producer.shutdown! } + + App::Producer.start! + rescue App::PreflightCheck::CheckFailure => e + Utility::Logger.error("Preflight check failed: #{e.message}") + exit(-1) + end +end diff --git a/lib/core/jobs/consumer.rb b/lib/core/jobs/consumer.rb index 3cb0b27c..c1581b7b 100644 --- a/lib/core/jobs/consumer.rb +++ b/lib/core/jobs/consumer.rb @@ -40,8 +40,8 @@ def subscribe!(index_name:) Utility::Logger.info("Starting a new consumer for #{@index_name} index") @index_name = index_name - start_timer_task! start_thread_pool! + start_timer_task! end def running? @@ -50,8 +50,8 @@ def running? def shutdown! Utility::Logger.info("Shutting down consumer for #{@index_name} index") - - timer_task.shutdown + @shutdown = true + # timer_task.shutdown pool.shutdown pool.wait_for_termination(@termination_timeout) reset_pool! @@ -62,7 +62,14 @@ def shutdown! attr_reader :pool, :timer_task def start_timer_task! - @timer_task = Concurrent::TimerTask.execute(execution_interval: @poll_interval, run_now: true) { execute } + loop do + break if @shutdown + + execute + + sleep(@poll_interval) + end + # @timer_task = Concurrent::TimerTask.execute(execution_interval: @poll_interval, run_now: true) { execute } end def start_thread_pool! diff --git a/lib/utility/logger.rb b/lib/utility/logger.rb index cd20095b..4115cb33 100644 --- a/lib/utility/logger.rb +++ b/lib/utility/logger.rb @@ -23,7 +23,7 @@ def level=(log_level) end def logger - @logger ||= defined?(::Settings) && ::Settings[:ecs_logging] ? EcsLogging::Logger.new(STDOUT) : ::Logger.new(STDOUT) + @logger ||= defined?(::Settings) && ::Settings[:ecs_logging] == true ? EcsLogging::Logger.new(STDOUT) : ::Logger.new(STDOUT) end SUPPORTED_LOG_LEVELS.each do |level|