提交 7ffdb70e authored 作者: Bret McDanel's avatar Bret McDanel

multi-server ("clustered") event scheduler

events are stored in MySQL so they survive a shutdown, reboot, crash, alien abduction and more!
events are any api command


git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk/contrib@15204 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 f90472b6
......@@ -23,6 +23,13 @@ with the programs whether commercial or FOSS.
== FILE LIST ==
scheduled_event.lua
LUA script that adds scheduler ability via a MySQL store.
Allows for many systems to process events to scale to enterprise capability
Events survive switch shutdown, restart, reboot, crash, etc
Simple DB schema which allows you to easily integrate into webapps
apiexec.pl
Execute api commands from the console/cron/windows scheduler/etc
......
-- Version: MPL 1.1
--
-- The contents of this file are subject to the Mozilla Public License Version
-- 1.1 (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
-- http://www.mozilla.org/MPL
--
-- Software distributed under the License is distributed on an "AS IS" basis
-- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- for the specific language governing rights and limitations under the
-- License
--
-- The Original Code is FreeSWITCH[tm] LUA event scheduler
--
-- The Initial Developer of the Original Code is
-- Bret McDanel <bret AT 0xdecafbad dot com>
--
-- Portions created by the Initial Developer are Copyright (C) 2007
-- the Initial Developer. All Rights Reserved
--
-- Contributor(s)
--
-- Why use this?
-- No reason in particular, however if you use sched_api and shut down you lose your scheduled events, by
-- placing them in a database you get the advantage of them being able to survive a shutdown/crash/reboot/etc
-- Additionally this script is written in a way to allow for multiple switch boxes to access the same database
-- and look for events to process, in this way you can scale this to a very large amount of actions
--
--
-- Usage: in FreeSWITCH console or fs_cli,
-- luarun scheduled_event.lua
-- starts the script - this is not needed if its auto loaded
-- luarun scheduled_event.lua <dbuser username> <dbhost hostname> <dbpass password> <dbname database_name>
-- changes the DB info allowing you to do load management, maintenence, or other things
-- luarun scheduled_event.lua stop
-- stops the running script
--
-- in lua.conf.xml:
-- <param name="startup-script" value="scheduled_event.lua"/>
--
--
-- You need to get "mysql.so" for lua and install it in <freeswitch install>/luasql/mysql.so
-- (or some other place that is in the search path)
--
-- Minimal DB schema **AUTOMAGICALLY CREATED IF IT DOES NOT EXIST** (at script start)
-- CREATE TABLE scheduler (
-- acctid int(11) NOT NULL auto_increment,
-- action varchar(1024) NOT NULL,
-- timestamp timestamp NOT NULL,
-- primary key (acctid)
-- );
--
-- "actions" in the scheduler table should be api commands eg:
-- insert into scheduler (action,timestamp) values ("pa call 1234",NOW())
--
--
-- Every "heartbeat" events are pulled 1 at a time using write locks on mysql
-- if your MySQL supports those locks, then only one process can access the DB at a time
-- events are immediately deleted, and then processed to keep the lock time low
-- failed events are NOT rescheduled
-- many boxes can pull events and process them, however I did not attempt to process more
-- events than time allows for in a given heartbeat interval, some backlog may exist which
-- may cause this script to totally freak
require "luasql.mysql"
-- Database setup
DATABASE = "database"
USERNAME = "dbuser"
PASSWORD = "het is geheim"
DBHOST = "localhost"
TABLENAME = "scheduler"
-- LOGGING
LOGLEVEL = "info"
-- PROGNAME
PROGNAME = "scheduled_event.lua"
function logger(message)
freeswitch.console_log(LOGLEVEL,"["..PROGNAME.."] "..message.."\n")
end
if argv[1] then
i=1
while argv[i] do
if argv[i] == "stop" then
local event = freeswitch.Event("custom", "lua::scheduled_event")
event:addHeader("Action", "stop")
event:fire()
logger("Sent stop message to lua script")
return
elseif (argv[i] == "dbuser") then
i=i+1
if argv[i] then
logger("Setting DB Username to "..argv[i])
USERNAME = argv[i]
else
logger("You must specify a username!")
end
elseif (argv[i] == "dbhost") then
i=i+1
if argv[i] then
logger("Setting DB Hostname to "..argv[i])
DBHOST = argv[i]
else
logger("You must specify a hostname!")
end
elseif (argv[i] == "dbpass") then
i=i+1
if argv[i] then
logger("Setting DB Password to "..argv[i])
PASSWORD = argv[i]
else
logger("You must specify a password!")
end
elseif (argv[i] == "dbname") then
i=i+1
if argv[i] then
logger("Setting DB to "..argv[i])
DATABASE = argv[i]
else
logger("You must specify a database name!")
end
end
i=i+1
end
return
end
--Main function starts here
logger("Starting")
-- ensure DB works, create table if it doesnt exist
env = assert (luasql.mysql())
dbcon = assert (env:connect(DATABASE,USERNAME,PASSWORD,DBHOST))
blah = assert(dbcon:execute("CREATE TABLE if not exists "..TABLENAME.." ("..
"acctid int(11) NOT NULL auto_increment,"..
"action varchar(1024) NOT NULL,"..
"timestamp timestamp NOT NULL,"..
"primary key (acctid)"..
")"))
dbcon:close()
env:close()
local event_name
local event_subclass
con = freeswitch.EventConsumer("all") -- too lazy to figure out why "heartbeat CUSTOM lua::scheduled_event"
-- does not work properly, that is really all we need
api = freeswitch.API()
if blah ~= 0 then
logger("Unable to connect to DB or create the table, something is broken.")
else
for e in (function() return con:pop(1) end) do
event_name = e:getHeader("Event-Name") or ""
event_subclass = e:getHeader("Event-Subclass") or ""
if(event_name == "HEARTBEAT") then
env = assert (luasql.mysql())
dbcon = assert (env:connect(DATABASE,USERNAME,PASSWORD,DBHOST))
while true do
assert (dbcon:execute("LOCK TABLE "..TABLENAME.." WRITE"))
cur = assert (dbcon:execute("select * from "..TABLENAME.." where timestamp < NOW() order by timestamp desc limit 1"))
row = cur:fetch({},"a")
if not row then
break
end
assert(dbcon:execute("delete from "..TABLENAME.." where acctid = "..row.acctid));
assert (dbcon:execute("UNLOCK TABLES"))
apicmd,apiarg = string.match(row.action,"(%w+) (.*)")
api:execute(apicmd,apiarg)
end
dbcon:close()
env:close()
else if (event_name == "CUSTOM" and event_subclass == "lua::scheduled_event") then
action = e:getHeader("Action") or ""
if (action == "stop") then
logger("got stop message, Exiting")
break
end
end
end
end
end
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论