module CPEE

This file is part of CPEE.

CPEE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

CPEE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with CPEE (file COPYING in the main directory). If not, see <www.gnu.org/licenses/>.

This file is part of CPEE.

CPEE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

CPEE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with CPEE (file COPYING in the main directory). If not, see <www.gnu.org/licenses/>.

This file is part of CPEE.

CPEE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

CPEE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with CPEE (file COPYING in the main directory). If not, see <www.gnu.org/licenses/>.

This file is part of CPEE.

CPEE is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

CPEE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with CPEE (file COPYING in the main directory). If not, see <www.gnu.org/licenses/>.

Constants

PROPERTIES_PATHS_FULL
PROPERTIES_PATHS_INDEX_ORDERED
PROPERTIES_PATHS_INDEX_UNORDERED
SERVER

Public Class Methods

cleanup_services(watchdog_start_off) click to toggle source
# File lib/cpee/implementation.rb, line 166
def self::cleanup_services(watchdog_start_off)
  return if watchdog_start_off
  Dir[File.join(__dir__,'..','..','server','routing','*.rb')].each do |s|
    s = s.sub(/\.rb$/,'')
    pid = (File.read(s + '.pid').to_i rescue nil)
    if !pid.nil? || (Process.kill(0, pid) rescue false)
      system "#{s}.rb stop 1>/dev/null 2>&1"
      puts "➡ Service #{File.basename(s,'.rb')} stopped ..."
    end
  end
end
implementation(opts) click to toggle source
# File lib/cpee/implementation.rb, line 56
def self::implementation(opts)
  opts[:instances]                  ||= File.expand_path(File.join(__dir__,'..','..','server','instances'))
  opts[:global_executionhandlers]   ||= File.expand_path(File.join(__dir__,'..','..','server','executionhandlers'))
  opts[:executionhandlers]          ||= ''
  opts[:topics]                     ||= File.expand_path(File.join(__dir__,'..','..','server','resources','topics.xml'))
  opts[:properties_init]            ||= File.expand_path(File.join(__dir__,'..','..','server','resources','properties.init'))
  opts[:properties_empty]           ||= File.expand_path(File.join(__dir__,'..','..','server','resources','properties.empty'))
  opts[:transformation_service]     ||= File.expand_path(File.join(__dir__,'..','..','server','resources','transformation.xml'))
  opts[:empty_dslx]                 ||= File.expand_path(File.join(__dir__,'..','..','server','resources','empty_dslx.xml'))
  opts[:notifications_init]         ||= File.expand_path(File.join(__dir__,'..','..','server','resources','notifications'))
  opts[:states]                     ||= File.expand_path(File.join(__dir__,'..','..','server','resources','states.xml'))
  opts[:watchdog_frequency]         ||= 7
  opts[:watchdog_start_off]         ||= false
  opts[:infinite_loop_stop]         ||= 10000

  ### set redis_cmd to nil if you want to do global
  ### at least redis_path or redis_url and redis_db have to be set if you do global
  opts[:redis_path]                 ||= 'redis.sock' # use e.g. /tmp/redis.sock for global stuff. Look it up in your redis config
  opts[:redis_db]                   ||= 0
  ### optional redis stuff
  opts[:redis_url]                  ||= nil
  opts[:redis_cmd]                  ||= 'redis-server --port 0 --unixsocket #redis_path# --unixsocketperm 600 --pidfile #redis_pid# --dir #redis_db_dir# --dbfilename #redis_db_name# --databases 1 --save 900 1 --save 300 10 --save 60 10000 --rdbcompression yes --daemonize yes'
  opts[:redis_pid]                  ||= 'redis.pid' # use e.g. /var/run/redis.pid if you do global. Look it up in your redis config
  opts[:redis_db_name]              ||= 'redis.rdb' # use e.g. /var/lib/redis.rdb for global stuff. Look it up in your redis config

  CPEE::redis_connect opts, 'Server Main'

  opts[:sse_keepalive_frequency]    ||= 10
  opts[:sse_connections]            = {}

  opts[:statemachine]               = CPEE::StateMachine.new opts[:states], %w{running simulating replaying finishing stopping abandoned finished} do |id|
    CPEE::Persistence::extract_item(id,opts,"state")
  end

  opts[:runtime_cmds]               << [
    "startclean", "Delete instances before starting.", Proc.new { |status|
      Dir.glob(File.expand_path(File.join(opts[:instances],'*'))).each do |d|
        FileUtils.rm_r(d) if File.basename(d) =~ /^\d+$/
      end
    }
  ]

  Proc.new do
    Dir[File.join(opts[:global_executionhandlers],'*','execution.rb')].each do |h|
      require h
    end unless opts[:global_executionhandlers].nil? || opts[:global_executionhandlers].strip == ''
    Dir[File.join(opts[:executionhandlers],'*','execution.rb')].each do |h|
      require h
    end unless opts[:executionhandlers].nil? || opts[:executionhandlers].strip == ''

    parallel do
      CPEE::watch_services(opts[:watchdog_start_off],opts[:redis_url],File.join(opts[:basepath],opts[:redis_path]),opts[:redis_db])
      EM.add_periodic_timer(opts[:watchdog_frequency]) do ### start services
        CPEE::watch_services(opts[:watchdog_start_off],opts[:redis_url],File.join(opts[:basepath],opts[:redis_path]),opts[:redis_db])
      end
      EM.defer do ### catch all sse connections
        CPEE::Notifications::sse_distributor(opts)
      end
      EM.add_periodic_timer(opts[:sse_keepalive_frequency]) do
        CPEE::Notifications::sse_heartbeat(opts)
      end
    end

    cleanup do
      CPEE::cleanup_services(opts[:watchdog_start_off])
    end

    interface 'main' do
      run CPEE::Instances, opts if get '*'
      run CPEE::NewInstance, opts if post 'instance-new'
      on resource '\d+' do |r|
        run CPEE::Info, opts if get
        run CPEE::DeleteInstance, opts if delete
      end
    end

    interface 'properties' do |r|
      id = r[:h]['RIDDL_DECLARATION_PATH'].split('/')[1].to_i
      use CPEE::Properties::implementation(id.to_i, opts)
    end

    interface 'notifications' do |r|
      id = r[:h]['RIDDL_DECLARATION_PATH'].split('/')[1].to_i
      use CPEE::Notifications::implementation(id.to_i, opts)
    end

    interface 'callbacks' do |r|
      id = r[:h]['RIDDL_DECLARATION_PATH'].split('/')[1].to_i
      use CPEE::Callbacks::implementation(id.to_i, opts)
    end
  end
end
redis_connect(opts,name=nil) click to toggle source
# File lib/cpee/redis.rb, line 18
def self::redis_connect(opts,name=nil)
  if opts[:redis_cmd].nil?
    begin
      if opts[:redis_path]
        opts[:redis_dyn] = Proc.new { |name| Redis.new(path: opts[:redis_path], db: opts[:redis_db], id: name.gsub(/[^a-zA-Z0-9]/,'-') ) }
      elsif opts[:redis_url]
        opts[:redis_dyn] = Proc.new { |name| Redis.new(url: opts[:redis_url], db: opts[:redis_db], id: name.gsub(/[^a-zA-Z0-9]/,'-') ) }
      else
        raise
      end
      opts[:redis] = opts[:redis_dyn].call name.gsub(/[^a-zA-Z0-9]/,'-')
      opts[:redis].dbsize
    rescue
      puts 'can not connect to redis. check if it is running and cpee is configured correctly ...'
      exit
    end
  else # we always assume file socket if redis is startet locally
    opts[:redis_dyn] = Proc.new { |name| Redis.new(path: File.join(opts[:basepath],opts[:redis_path]), db: opts[:redis_db].to_i, id: name.gsub(/[^a-zA-Z0-9]/,'-') ) }
    tried = false
    begin
      opts[:redis] = opts[:redis_dyn].call name.gsub(/[^a-zA-Z0-9]/,'-')
      opts[:redis].dbsize
    rescue => e
      puts e
      res = unless tried
        rcmd = opts[:redis_cmd]
        rcmd.gsub! /#redis_path#/, File.join(opts[:basepath],opts[:redis_path])
        rcmd.gsub! /#redis_db_dir#/, opts[:basepath]
        rcmd.gsub! /#redis_db_name#/, opts[:redis_db_name]
        rcmd.gsub! /#redis_pid#/, File.join(opts[:basepath],opts[:redis_pid])
        puts 'starting redis ... it will keep running, just to let you know ...'
        system rcmd
      else
        true
      end
      if res
        tried = true
        puts 'waiting for successful start ...'
        sleep 1
        retry
      else
        puts 'can not start redis. check if cpee is configured correctly ...'
        exit
      end
    end
  end
end
watch_services(watchdog_start_off,url,path,db) click to toggle source
# File lib/cpee/implementation.rb, line 149
def self::watch_services(watchdog_start_off,url,path,db)
  return if watchdog_start_off
   EM.defer do
     Dir[File.join(__dir__,'..','..','server','routing','*.rb')].each do |s|
       s = s.sub(/\.rb$/,'')
       pid = (File.read(s + '.pid').to_i rescue nil)
       if (pid.nil? || !(Process.kill(0, pid) rescue false)) && !File.exist?(s + '.lock')
         if url.nil?
           system "#{s}.rb -p \"#{path}\" -d #{db} restart 1>/dev/null 2>&1"
         else
           system "#{s}.rb -u \"#{url}\" -d #{db} restart 1>/dev/null 2>&1"
         end
         puts "➡ Service #{File.basename(s,'.rb')} started ..."
       end
     end
  end
end