flok 0.0.36 → 0.0.38

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -0
  3. data/app/drivers/chrome/build_context.rb +1 -1
  4. data/app/drivers/chrome/config.yml +10 -0
  5. data/app/drivers/chrome/pipe.rb +24 -1
  6. data/app/drivers/chrome/src/persist.js +29 -0
  7. data/app/drivers/chrome/src/sockio.js +3 -1
  8. data/app/drivers/chrome/src/vendor/store2.js +3 -0
  9. data/app/kern/callout.js +55 -0
  10. data/app/kern/controller.js +3 -0
  11. data/app/kern/crc32.js +22 -0
  12. data/app/kern/dispatch.js +16 -0
  13. data/app/kern/mod/event.js +3 -0
  14. data/app/kern/mod/persist.js +1 -0
  15. data/app/kern/mod/timer.js +5 -0
  16. data/app/kern/pagers/mem_pager.js +2 -0
  17. data/app/kern/pagers/sockio_pager.js +66 -0
  18. data/app/kern/pagers/spec0.js +35 -0
  19. data/app/kern/pagers/spec1.js +24 -0
  20. data/app/kern/pagers/spec2.js +31 -0
  21. data/app/kern/services/test.rb +7 -0
  22. data/app/kern/services/vm.rb +141 -0
  23. data/app/kern/spec_helper.js +5 -0
  24. data/bin/flok +27 -5
  25. data/docs/callout.md +8 -0
  26. data/docs/client_api.md +1 -1
  27. data/docs/compilation.md +14 -8
  28. data/docs/controllers.md +2 -1
  29. data/docs/datatypes.md +3 -1
  30. data/docs/environmentals.md +6 -0
  31. data/docs/interactive.md +6 -1
  32. data/docs/kernel_api.md +3 -0
  33. data/docs/mod/event.md +5 -1
  34. data/docs/mod/persist.md +14 -31
  35. data/docs/mod/timer.md +4 -2
  36. data/docs/project.md +16 -5
  37. data/docs/scheduling.md +1 -0
  38. data/docs/services.md +141 -56
  39. data/docs/services/vm.md +128 -0
  40. data/docs/services/vm/pagers.md +46 -0
  41. data/lib/flok/build.rb +11 -16
  42. data/lib/flok/platform.rb +29 -6
  43. data/lib/flok/project_template/app/scripts/script.js +3 -0
  44. data/lib/flok/project_template/app/services/service.rb +1 -0
  45. data/lib/flok/project_template/config/config.yml +1 -0
  46. data/lib/flok/project_template/config/platforms/chrome/config.yml +1 -0
  47. data/lib/flok/project_template/config/services.rb +1 -0
  48. data/lib/flok/service_compiler_templates/services.js.erb +78 -9
  49. data/lib/flok/services_compiler.rb +117 -20
  50. data/lib/flok/user_compiler.rb +14 -6
  51. data/lib/flok/user_compiler_templates/ctable.js.erb +10 -0
  52. data/lib/flok/version.rb +1 -1
  53. data/spec/env/etc.rb +1 -1
  54. data/spec/env/global.rb +2 -0
  55. data/spec/env/iface.rb +20 -4
  56. data/spec/env/kern.rb +8 -3
  57. data/spec/etc/cli_spec.rb +319 -165
  58. data/spec/etc/lib/assets/config.yml +3 -0
  59. data/spec/etc/lib/platform_spec.rb +14 -10
  60. data/spec/etc/lib/project_spec.rb +22 -0
  61. data/spec/etc/service_compiler/config0.rb +1 -0
  62. data/spec/etc/service_compiler/config1.rb +1 -0
  63. data/spec/etc/service_compiler/config2.rb +3 -0
  64. data/spec/etc/service_compiler/service0.rb +22 -6
  65. data/spec/etc/service_compiler/service1.rb +26 -0
  66. data/spec/etc/service_compiler/service_bad_type.rb +20 -0
  67. data/spec/etc/services_compiler_spec.rb +35 -16
  68. data/spec/etc/user_compiler/data.js +2 -0
  69. data/spec/etc/user_compiler_spec.rb +7 -1
  70. data/spec/iface/driver/persist_spec.rb +106 -0
  71. data/spec/iface/driver/pipe_spec.rb +5 -0
  72. data/spec/iface/kern/ping_spec.rb +4 -3
  73. data/spec/kern/assets/blank.rb +0 -0
  74. data/spec/kern/assets/service0.rb +24 -0
  75. data/spec/kern/assets/service1.rb +22 -0
  76. data/spec/kern/assets/service2.rb +27 -0
  77. data/spec/kern/assets/service_config0.rb +2 -0
  78. data/spec/kern/assets/service_config1.rb +2 -0
  79. data/spec/kern/assets/service_controller0.rb +13 -0
  80. data/spec/kern/assets/service_controller1.rb +32 -0
  81. data/spec/kern/assets/service_controller2.rb +38 -0
  82. data/spec/kern/assets/service_controller3.rb +38 -0
  83. data/spec/kern/assets/vm/config0.rb +2 -0
  84. data/spec/kern/assets/vm/config1.rb +12 -0
  85. data/spec/kern/assets/vm/config2.rb +12 -0
  86. data/spec/kern/assets/vm/config3.rb +12 -0
  87. data/spec/kern/assets/vm/controller0.rb +8 -0
  88. data/spec/kern/assets/vm/controller1.rb +18 -0
  89. data/spec/kern/assets/vm/controller2.rb +18 -0
  90. data/spec/kern/assets/vm/controller3.rb +20 -0
  91. data/spec/kern/assets/vm/controller4.rb +22 -0
  92. data/spec/kern/assets/vm/controller5.rb +22 -0
  93. data/spec/kern/assets/vm/controller6.rb +21 -0
  94. data/spec/kern/assets/vm/service0.rb +24 -0
  95. data/spec/kern/assets/vm/service_controller0.rb +7 -0
  96. data/spec/kern/callout_spec.rb +153 -0
  97. data/spec/kern/functions_spec.rb +29 -0
  98. data/spec/kern/service_controller_spec.rb +213 -0
  99. data/spec/kern/vm_service_spec.rb +195 -0
  100. metadata +98 -12
  101. data/app/kern/services/rest.rb +0 -310
  102. data/app/kern/services/timer.rb +0 -30
  103. data/docs/services/timer.md +0 -21
  104. data/spec/kern/assets/rest_service.rb +0 -20
  105. data/spec/kern/assets/timer_service.rb +0 -19
  106. data/spec/kern/timer_service_spec.rb +0 -40
data/lib/flok/platform.rb CHANGED
@@ -12,17 +12,40 @@ module Flok
12
12
  end
13
13
 
14
14
  #Get a list of modules for a particular environment for a platform
15
- def self.mods platform, environment
15
+ def self.mods environment
16
16
  #Create array that looks like a javascript array with single quotes
17
- mods = self.config_yml(platform, environment)['mods']
17
+ mods = self.config_yml(environment)['mods']
18
18
  end
19
19
 
20
- #Get all config.yml information for a platform
21
- def self.config_yml platform, environment
22
- driver_config = YAML.load_file("./app/drivers/#{platform}/config.yml")
23
- raise "No config.yml found in your 'platform: #{platform}' driver" unless driver_config
20
+ def self.defines environment
21
+ #Just converting an array into a hash of true values for easier lookup
22
+ hash = {}
23
+ defines_arr = self.config_yml(environment)['defines']
24
+ if defines_arr
25
+ defines_arr.each do |e|
26
+ hash[e] = true
27
+ end
28
+ end
29
+
30
+ return hash
31
+ end
32
+
33
+ #Get all config.yml information for a config_yml file based on FLOK_CONFIG
34
+ def self.config_yml environment
35
+ #Get the config.yml path
36
+ config_yml_path = ENV['FLOK_CONFIG']
37
+ if config_yml_path
38
+ raise "You didn't pass a FLOK_CONFIG variable for the config.yml" unless config_yml_path
39
+ raise "The FLOK_CONFIG given: #{config_yml_path.inspect} does not contain a file (config.yml)" unless File.exists?(config_yml_path)
40
+ else
41
+ #$stderr.puts "Warning: You didn't specify FLOK_CONFIG, Using default config of ./app/drivers/#{ENV['PLATFORM']}/config.yml"
42
+ config_yml_path = "./app/drivers/#{ENV['PLATFORM']}/config.yml"
43
+ end
44
+
45
+ driver_config = YAML.load_file(config_yml_path)
24
46
  return driver_config[environment]
25
47
  end
48
+
26
49
  end
27
50
 
28
51
  #Alias
@@ -0,0 +1,3 @@
1
+ //You shouldn't have many scripts in here, but any javascript files in ./app/scripts/*.js could be
2
+ //used if you need access to (small amounts) of static data, etc. These files are merged with the final
3
+ //kernel binary.
@@ -0,0 +1 @@
1
+ #Your services should go into this file, you may name your files anything and delete this file
@@ -0,0 +1 @@
1
+ <%= File.read("./app/drivers/ENV['PLATFORM']/")
@@ -0,0 +1 @@
1
+ <%= File.read(File.join(File.dirname(__FILE__), "../../../app/drivers/#{ENV['PLATFORM']}/config.yml")) %>
@@ -0,0 +1 @@
1
+ #Services
@@ -1,13 +1,82 @@
1
1
  <% @services.each do |s| %>
2
- //////////////////////////////////////////////////
3
- //Start of <%= s.name %> on_init
4
- <%= s.get_on_init %>
5
- //////////////////////////////////////////////////
2
+ //Variables
3
+ var <%= s.name %>_sessions = {}; //Currently connected clients
4
+ var <%= s.name %>_n_sessions = 0; //Number of sessions
6
5
 
7
- //////////////////////////////////////////////////
8
- //Start of <%= s.name %> on_request
9
- function service_<%= s.name %>_req(info, ep, ename) {
10
- <%= s.get_on_request %>
6
+ //Static global
7
+ <%= s._global %>
8
+
9
+ //Start of <%= s.name %> on_wakeup
10
+ function <%= s.name %>_on_wakeup() {
11
+ //Timer related
12
+ /////////////////////////////////////////////////////////////////////////////////////
13
+ //The timer base pointer for incomming callout events
14
+ <%= s.name %>_timer_bp = tels(1);
15
+ reg_evt(<%= s.name %>_timer_bp, <%= s.name %>_handle_timer_events);
16
+
17
+ //Tell the timer to notify our timer event handlers
18
+ //The name is randomly generated for each one
19
+ <% s.every_handlers.each do |h| %>
20
+ reg_interval(<%= s.name %>_timer_bp, '<%= h[:name] %>', <%= h[:ticks] %>);
21
+ <% end %>
22
+ /////////////////////////////////////////////////////////////////////////////////////
23
+
24
+ <%= s._on_wakeup %>
25
+ }
26
+
27
+ function <%= s.name %>_on_sleep() {
28
+ //Do not receive anymore timer events
29
+ dereg_evt(<%= s.name %>_timer_bp);
30
+
31
+ <%= s._on_sleep %>
32
+ }
33
+
34
+ function <%= s.name %>_on_connect(bp) {
35
+ var sessions = <%= s.name %>_sessions;
36
+ <%= s.name %>_n_sessions += 1;
37
+
38
+ //First connection
39
+ if (<%= s.name %>_n_sessions === 1) {
40
+ <%= s.name %>_on_wakeup();
41
+ }
42
+
43
+ sessions[bp] = true;
44
+ <%= s._on_connect %>
45
+ }
46
+
47
+ function <%= s.name %>_on_disconnect(bp) {
48
+ var sessions = <%= s.name %>_sessions;
49
+
50
+ <%= s.name %>_n_sessions -= 1;
51
+ delete sessions[bp];
52
+
53
+ <%= s._on_disconnect %>
54
+
55
+ //No more connections
56
+ if (<%= s.name %>_n_sessions === 0) {
57
+ <%= s.name %>_on_sleep();
58
+ }
59
+
60
+ }
61
+
62
+ //'Event' handlers
63
+ <% s.event_handlers.each do |h| %>
64
+ function <%= s.name %>_on_<%= h[:name] %>(bp, params) {
65
+ var sessions = <%= s.name %>_sessions;
66
+ <%= h[:str] %>
67
+ }
68
+ <% end %>
69
+
70
+ //Timer receivers
71
+ /////////////////////////////////////////////////////////////////////
72
+ function <%= s.name %>_handle_timer_events(ep, ename, info) {
73
+ var sessions = <%= s.name %>_sessions;
74
+
75
+ <% s.every_handlers.each do |h| %>
76
+ if (ename === '<%= h[:name] %>') {
77
+ <%= h[:str] %>
78
+ }
79
+ <% end %>
11
80
  }
12
- //////////////////////////////////////////////////
81
+ /////////////////////////////////////////////////////////////////////
13
82
  <% end %>
@@ -1,22 +1,28 @@
1
1
  #Compile a controller ruby file into a javascript string
2
+ require 'active_support'
3
+ require 'active_support/core_ext/numeric'
2
4
 
3
5
  require 'erb'
4
6
  module Flok
5
7
  module ServicesCompiler
6
8
  #Compile a ruby file containing flok controller definitions (from the services)
7
- def self.compile rb_src
9
+ #The config is outlined in the documentation under docs/services.md
10
+ def self.compile rb_src, rb_config
11
+ #Execute the configuration file first
12
+ config_context = ServicesCompilerConfigContext.new
13
+ config_context.instance_eval(rb_config, __FILE__, __LINE__)
14
+
8
15
  #Execute code in this context, the context will hold all the information
9
16
  #that is used to then generate code
10
- context = ServicesCompilerContext.new
17
+ context = ServicesCompilerContext.new(config_context)
11
18
  context.instance_eval(rb_src, __FILE__, __LINE__)
19
+ context.ready
12
20
 
13
21
  @src = ""
14
22
  services_erb = File.read File.join(File.dirname(__FILE__), "./service_compiler_templates/services.js.erb")
15
23
  services_renderer = ERB.new(services_erb)
16
24
  @src << services_renderer.result(context.get_binding)
17
25
 
18
- #puts @src
19
-
20
26
  return @src
21
27
  end
22
28
  end
@@ -24,29 +30,71 @@ end
24
30
 
25
31
  #Compiler executes all rb code inside this context
26
32
  module Flok
27
- class ServicesCompilerContext
28
- attr_accessor :services
33
+ class ServicesCompilerConfigContext
34
+ #Each service instance contains a :instance_name and :class
35
+ attr_accessor :service_instances
29
36
 
30
37
  def initialize
38
+ @service_instances = []
39
+ end
40
+
41
+ def service_instance instance_name, name, options={}
42
+ @service_instances.push({
43
+ :instance_name => instance_name,
44
+ :class => name,
45
+ :options => options
46
+ })
47
+ end
48
+ end
49
+
50
+ class ServicesCompilerContext
51
+ attr_accessor :services, :config
52
+
53
+ def initialize config_context
54
+ @config = config_context
55
+
56
+ #A hash containing the 'class' name of the service to a block that can be used with Service.new
57
+ @_services = {}
58
+
31
59
  @services = []
32
60
  end
33
61
 
62
+ def ready
63
+ #Create an array from the service_instances where each element in the array is the full code of the service
64
+ @config.service_instances.each do |i|
65
+ #Get the instance name and class name of the service, normally defined in a ./config/services.rb file
66
+ sname = i[:instance_name]
67
+ sclass = i[:class]
68
+ soptions = i[:options]
69
+
70
+ sblock = @_services[sclass]
71
+ raise "No service found for service_name: #{sclass.inspect} when trying to create service with instance name #{sname.inspect}. @_services contained: #{@_services.inspect} \n@config.service_instances contained: #{@config.service_instances.inspect}" unless sblock
72
+ service = Service.new(sname, soptions)
73
+ service.instance_eval(&sblock)
74
+ @services << service
75
+ end
76
+ end
77
+
34
78
  def get_binding
35
79
  return binding
36
80
  end
37
81
 
38
82
  def service name, &block
39
- @services << Service.new(name, &block)
83
+ @_services[name] = block
40
84
  end
41
85
  end
42
86
 
43
87
  class Service
44
- attr_accessor :name
45
- def initialize name, &block
88
+ attr_accessor :name, :_global, :_on_wakeup, :_on_sleep, :_on_connect, :_on_disconnect, :event_handlers, :every_handlers, :options
89
+ def initialize name, options
46
90
  @name = name
47
- @block = block
91
+ @options = options
92
+
93
+ #These are the 'on' handlers
94
+ @event_handlers = []
48
95
 
49
- self.instance_eval(&block)
96
+ #These are for every 5.seconds
97
+ @every_handlers = []
50
98
  end
51
99
 
52
100
  def get_on_init
@@ -57,18 +105,67 @@ module Flok
57
105
  return @on_request
58
106
  end
59
107
 
60
- def on_init str
61
- @on_init = macro(str)
108
+ def global(str)
109
+ render = ERB.new(str)
110
+ str = render.result(binding)
111
+ @_global = str
112
+ end
113
+
114
+ def on_wakeup(str)
115
+ render = ERB.new(str)
116
+ str = render.result(binding)
117
+ @_on_wakeup = str
118
+ end
119
+
120
+ def on_sleep(str)
121
+ render = ERB.new(str)
122
+ str = render.result(binding)
123
+
124
+ @_on_sleep = str
125
+ end
126
+
127
+ def on_connect(str)
128
+ render = ERB.new(str)
129
+ str = render.result(binding)
130
+ @_on_connect = str
62
131
  end
63
132
 
64
- def on_request str
65
- @on_request = macro(str)
133
+ def on_disconnect(str)
134
+ render = ERB.new(str)
135
+ str = render.result(binding)
136
+ @_on_disconnect = str
137
+ end
138
+
139
+ def on(name, str)
140
+ render = ERB.new(str)
141
+ str = render.result(binding)
142
+
143
+ @event_handlers << {
144
+ :name => name,
145
+ :str => str
146
+ }
147
+ end
148
+
149
+ def every(seconds, str)
150
+ @every_handlers << {
151
+ :name => "#{seconds}_sec_#{SecureRandom.hex[0..6]}",
152
+ :ticks => seconds*4,
153
+ :str => str
154
+ }
155
+ end
156
+
157
+ def type str
158
+ @_type = str.to_s
159
+ unless ["daemon", "agent"].include? @_type
160
+ raise "You gave a type for the service, #{@_type.inspect} but this wasn't a valid type of service. Should be \
161
+ either 'daemon' or 'agent'"
162
+ end
66
163
  end
67
164
 
68
165
  def macro text
69
- out = StringIO.new
166
+ #out = StringIO.new
70
167
 
71
- text.split("\n").each do |l|
168
+ #text.split("\n").each do |l|
72
169
  ##Request(vc_name, spot_name, context) macro
73
170
  #if l =~ /Request/
74
171
  #l.strip!
@@ -84,11 +181,11 @@ module Flok
84
181
  #out << %{
85
182
  #}
86
183
  #else
87
- out.puts l
184
+ #out.puts l
88
185
  #end
89
- end
186
+ #end
90
187
 
91
- return out.string
188
+ #return out.string
92
189
  end
93
190
  end
94
191
  end
@@ -15,8 +15,6 @@ module Flok
15
15
  ctable_renderer = ERB.new(ctable_erb)
16
16
  @src << ctable_renderer.result(context.get_binding)
17
17
 
18
- #puts @src
19
-
20
18
  return @src
21
19
  end
22
20
  end
@@ -194,6 +192,9 @@ module Flok
194
192
  //Free +1 because that will be the 'main' view
195
193
  main_q.push([1, "if_free_view", embeds[i][j]+1]);
196
194
 
195
+ //Call dealloc on the controller
196
+ tel_deref(embeds[i][j]).cte.__dealloc__(embeds[i][j]);
197
+
197
198
  <% if @debug %>
198
199
  var vp = embeds[i][j]+1;
199
200
  //First locate spot this view belongs to in reverse hash
@@ -228,7 +229,7 @@ module Flok
228
229
  }]);
229
230
  }
230
231
  out.puts res
231
- #Request(service_name, payload, event_name_cb)
232
+ #Request(service_instance_name, ename, info)
232
233
  elsif l =~ /Request/
233
234
  l.strip!
234
235
  l.gsub!(/Request\(/, "")
@@ -237,11 +238,13 @@ module Flok
237
238
  o = l.split(",").map{|e| e.strip}
238
239
 
239
240
  name = o.shift.gsub(/"/, "")
241
+ ename = o.shift.gsub(/"/, "")
240
242
  info = o.shift.gsub(/"/, "")
241
- event_name = o.shift
243
+
244
+ raise "You tried to Request the service #{name.inspect}, but you haven't added that to your 'services' for this controller (#{@controller.name.inspect})" unless @controller._services.include? name
242
245
 
243
246
  out << %{
244
- service_#{name}_req(#{info}, __base__, #{event_name});
247
+ #{name}_on_#{ename}(__base__, #{info});
245
248
  }
246
249
  else
247
250
  out.puts l
@@ -265,12 +268,13 @@ module Flok
265
268
  end
266
269
 
267
270
  class UserCompilerController
268
- attr_accessor :name, :spots, :macros
271
+ attr_accessor :name, :spots, :macros, :_services
269
272
  def initialize name, ctx, &block
270
273
  @name = name
271
274
  @ctx = ctx
272
275
  @spots = ['main']
273
276
  @macros = {}
277
+ @_services = []
274
278
 
275
279
  self.instance_eval(&block)
276
280
  end
@@ -285,6 +289,10 @@ module Flok
285
289
  @spots += spots
286
290
  end
287
291
 
292
+ def services *instance_names
293
+ @_services = instance_names.map{|e| e.to_s}
294
+ end
295
+
288
296
  #Pass through action
289
297
  def action name, &block
290
298
  @ctx.action self, name, &block
@@ -1,6 +1,16 @@
1
1
  ctable = {
2
2
  <% @controllers.each do |c| %>
3
3
  <%= c.name %>: {
4
+ __init__: function(__base__) {
5
+ <% c._services.each do |s| %>
6
+ <%= s %>_on_connect(__base__);
7
+ <% end %>
8
+ },
9
+ __dealloc__: function(__base__) {
10
+ <% c._services.each do |s| %>
11
+ <%= s %>_on_disconnect(__base__);
12
+ <% end %>
13
+ },
4
14
  name: '<%= c.name %>',
5
15
  root_view: '<%= c.name %>',
6
16
  spots: <%= c.spots.to_json %>,
data/lib/flok/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Flok
2
- VERSION = "0.0.36"
2
+ VERSION = "0.0.38"
3
3
  end