webmcp
changeset 317:732c4d53a823
Invoke Moonbridge's listen function without delay (requires passing http_options as argument); Code cleanup
author | jbe |
---|---|
date | Mon Mar 23 19:05:32 2015 +0100 (2015-03-23) |
parents | a2c733535b8e |
children | f5660406ad3b |
files | framework/bin/mcp.lua framework/env/request/__init.lua framework/env/request/get_http_options.lua framework/env/request/set_http_options.lua |
line diff
1.1 --- a/framework/bin/mcp.lua Mon Mar 23 16:05:56 2015 +0100 1.2 +++ b/framework/bin/mcp.lua Mon Mar 23 19:05:32 2015 +0100 1.3 @@ -8,7 +8,16 @@ 1.4 WEBMCP_VERSION = "2.0.0" 1.5 --//-- 1.6 1.7 --- allow control of global environment 1.8 +--[[-- 1.9 +_G 1.10 + 1.11 +A reference to the global namespace. To avoid accidental programming errors, global variables cannot be set directly, but they must be set through the _G reference, e.g. use _G.foo = true to set the variable "foo" to a value of true. 1.12 + 1.13 +The only exception is the <framework>/env/__init.lua file and the <application>/env/__init.lua file, in which global variables may be set without using the _G reference. 1.14 + 1.15 +Note that the global namespace may or may not be shared between requests (Moonbridge creates multiple forks of the Lua machine). To set variables that are to be cleared after the request has been finished, an application may use the "app" table, e.g. app.foo = true to set the variable app.foo to a value of true, which will be cleared automatically when the request has ended. 1.16 + 1.17 +--]]-- 1.18 local _G = _G 1.19 local allowed_globals = {} 1.20 local global_metatable = { 1.21 @@ -17,7 +26,23 @@ 1.22 _G[key] = value 1.23 end 1.24 } 1.25 -_ENV = setmetatable({}, global_metatable) 1.26 +_ENV = setmetatable( 1.27 + {}, -- proxy environment used within mcp.lua and by all chunks loaded through loadcached(...) 1.28 + global_metatable 1.29 +) 1.30 +local function protect_globals() -- called before first configuration file is loaded 1.31 + function global_metatable.__newindex(self, key, value) 1.32 + if allowed_globals[key] then 1.33 + _G[key] = value 1.34 + else 1.35 + if type(key) == "string" and string.match(key, "^[A-Za-z_][A-Za-z_0-9]*$") then 1.36 + error('Attempt to set global variable "' .. key .. '" (hint: use _G.' .. key .. '=<value> to override protection mechnamism)', 2) 1.37 + else 1.38 + error('Attempt to set global variable', 2) 1.39 + end 1.40 + end 1.41 + end 1.42 +end 1.43 1.44 --[[-- 1.45 lua_func = -- compiled Lua function 1.46 @@ -57,7 +82,6 @@ 1.47 1.48 A constant set to "listen" in case of a network request, or set to "interactive" in case of interactive mode. 1.49 --]]-- 1.50 --- check if interactive mode 1.51 if listen then -- defined by moonbridge 1.52 WEBMCP_MODE = "listen" 1.53 else 1.54 @@ -169,6 +193,7 @@ 1.55 -- autoloader system for WebMCP environment "$WEBMCP_FRAMEWORK_PATH/env/", 1.56 -- application environment extensions "$WEBMCP_BASE_PATH/env/" 1.57 -- and models "$WEBMCP_BASE_PATH/model/" 1.58 +local root_init -- function which executes the __init.lua file in the environment's root 1.59 do 1.60 local weakkey_mt = { __mode = "k" } 1.61 local autoloader_category = setmetatable({}, weakkey_mt) 1.62 @@ -253,75 +278,74 @@ 1.63 return rawget(self, key) 1.64 end 1.65 install_autoloader(_G, nil, "") 1.66 - try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua") 1.67 - try_exec(WEBMCP_BASE_PATH .. "env/__init.lua") 1.68 -end 1.69 - 1.70 --- replace Moonbridge listen function 1.71 -local moonbridge_listen = listen 1.72 -local listeners = {} 1.73 -function listen(args) 1.74 - listeners[#listeners+1] = args 1.75 + function root_init() -- upvalue 1.76 + try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua") 1.77 + try_exec(WEBMCP_BASE_PATH .. "env/__init.lua") 1.78 + end 1.79 end 1.80 1.81 --- prohibit (unintended) definition of new global variables 1.82 -function global_metatable.__newindex(self, key, value) 1.83 - if not allowed_globals[key] then 1.84 - error("Setting of global variable prohibited", 2) 1.85 - end 1.86 - _G[key] = value 1.87 -end 1.88 - 1.89 --- execute configurations and pre-fork initializers 1.90 -for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do 1.91 - execute.config(config_name) 1.92 -end 1.93 -execute.prefork_initializers() 1.94 - 1.95 -- define post-fork initialization function (including loading of "multirand" library) 1.96 local function postfork_init() 1.97 _G.multirand = require "multirand" 1.98 execute.postfork_initializers() 1.99 end 1.100 1.101 --- interactive console mode 1.102 +-- prepare for interactive or listen mode 1.103 if WEBMCP_MODE == "interactive" then 1.104 - postfork_init() 1.105 - trace.disable() -- avoids memory leakage 1.106 -end 1.107 - 1.108 --- invoke moonbridge 1.109 -if WEBMCP_MODE == "listen" then 1.110 - local http_options = request.get_http_options() 1.111 - local min_requests_per_fork = http_options.min_requests_per_fork or 50 1.112 - local max_requests_per_fork = http_options.max_requests_per_fork or 100 1.113 + function listen() -- overwrite Moonbridge's listen function 1.114 + -- ignore listen function calls for interactive mode 1.115 + end 1.116 + trace.disable() -- avoids memory leakage when scripts are running endlessly 1.117 +else 1.118 + local moonbridge_listen = listen 1.119 local http = require("moonbridge_http") 1.120 - for i, listener in ipairs(listeners) do 1.121 + function listen(args) -- overwrite Moonbridge's listen function 1.122 + local http_options = args.http_options or {} 1.123 + local min_requests_per_fork = http_options.min_requests_per_fork or 50 1.124 + local max_requests_per_fork = http_options.max_requests_per_fork or 100 1.125 local interval_handlers = {} 1.126 - for j, entry in ipairs(listener) do 1.127 - if entry.proto == "interval" then 1.128 - local name = entry.name or "Unnamed interval #" .. #interval_handlers+1 1.129 - interval_handlers[name] = entry.handler 1.130 - entry.name = name 1.131 + for j, listener in ipairs(args) do 1.132 + if listener.proto == "interval" then 1.133 + local name = listener.name or "Unnamed interval #" .. #interval_handlers+1 1.134 + interval_handlers[name] = listener.handler 1.135 + listener.name = name 1.136 end 1.137 end 1.138 local request_count = 0 1.139 local function inner_handler(http_request) 1.140 + request.initialize() 1.141 request.handler(http_request, request_count >= max_requests_per_fork) 1.142 end 1.143 local outer_handler = http.generate_handler(inner_handler, http_options) 1.144 - listener.prepare = postfork_init 1.145 - listener.connect = function(socket) 1.146 + args.prepare = postfork_init 1.147 + args.connect = function(socket) 1.148 request_count = request_count + 1 1.149 - request.initialize() 1.150 if socket.interval then 1.151 + request.initialize() 1.152 interval_handlers[socket.interval]() 1.153 else 1.154 outer_handler(socket) 1.155 end 1.156 return request_count < min_requests_per_fork 1.157 end 1.158 - listener.finish = execute.finalizers 1.159 - moonbridge_listen(listener) 1.160 + args.finish = execute.finalizers 1.161 + moonbridge_listen(args) 1.162 end 1.163 end 1.164 + 1.165 +-- execute the __init.lua file in the environment's root 1.166 +root_init() 1.167 + 1.168 +-- prohibit (unintended) definition of new global variables 1.169 +protect_globals() 1.170 + 1.171 +-- execute configurations and pre-fork initializers 1.172 +for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do 1.173 + execute.config(config_name) 1.174 +end 1.175 +execute.prefork_initializers() 1.176 + 1.177 +-- perform post-fork initializations in case of interactive mode 1.178 +if WEBMCP_MODE == "interactive" then 1.179 + postfork_init() 1.180 +end
2.1 --- a/framework/env/request/__init.lua Mon Mar 23 16:05:56 2015 +0100 2.2 +++ b/framework/env/request/__init.lua Mon Mar 23 19:05:32 2015 +0100 2.3 @@ -1,7 +1,6 @@ 2.4 request._initializers = {} 2.5 request._in_progress = false 2.6 2.7 --- initialize once 2.8 request._mime_types = { 2.9 "html", "text/html", 2.10 "css", "text/css", 2.11 @@ -14,12 +13,10 @@ 2.12 "pdf", "application/pdf", 2.13 "txt", "text/plain" 2.14 } 2.15 -request._absolute_baseurl = nil 2.16 -request._http_options = {} 2.17 2.18 request.for_each(function() 2.19 2.20 - -- configurable 2.21 + request._absolute_baseurl = nil 2.22 request._response_headers = {} 2.23 request._force_absolute_baseurl = false 2.24 request._perm_params = {} 2.25 @@ -27,8 +24,6 @@ 2.26 request._cache = false 2.27 request._cache_manual = false 2.28 request._cache_time = 3600 2.29 - 2.30 - -- non-configurable 2.31 request._relative_baseurl = nil 2.32 request._http_request = nil 2.33 request._status = nil
3.1 --- a/framework/env/request/get_http_options.lua Mon Mar 23 16:05:56 2015 +0100 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,10 +0,0 @@ 3.4 ---[[-- 3.5 -request.get_http_options() 3.6 - 3.7 -Returns the table filled by request.set_http_options(). The return value can be passed to Moonbridge's HTTP request handler generator. 3.8 - 3.9 ---]]-- 3.10 - 3.11 -function request.get_http_options() 3.12 - return request._http_options 3.13 -end
4.1 --- a/framework/env/request/set_http_options.lua Mon Mar 23 16:05:56 2015 +0100 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,14 +0,0 @@ 4.4 ---[[-- 4.5 -request.set_http_options{ 4.6 - ... 4.7 -} 4.8 - 4.9 -To be called in a configuration file to set parameters for the Moonbridge HTTP module. 4.10 - 4.11 ---]]-- 4.12 - 4.13 -function request.set_http_options(args) 4.14 - for key, value in pairs(args) do 4.15 - request._http_options[key] = value 4.16 - end 4.17 -end