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
@@ -0,0 +1,3 @@
1
+ DEBUG:
2
+ mods:
3
+ - hello
@@ -1,5 +1,6 @@
1
1
  Dir.chdir File.join File.dirname(__FILE__), '../../../'
2
2
  require './lib/flok'
3
+ require './spec/lib/temp_dir'
3
4
 
4
5
  #We are using the CHROME module as a test because it's fairly standardized
5
6
 
@@ -11,23 +12,26 @@ RSpec.describe "lib/platform" do
11
12
  expect(platforms).to include("chrome")
12
13
  end
13
14
 
14
- it "can list platform specific config_yml" do
15
- debug_yml = Flok::Platform.config_yml("chrome", "DEBUG")
16
- release_yml = Flok::Platform.config_yml("chrome", "RELEASE")
15
+ it "can list specific config_yml" do
16
+ debug_yml = Flok::Platform.config_yml("DEBUG")
17
+ release_yml = Flok::Platform.config_yml("RELEASE")
17
18
 
18
- expect(debug_yml.keys).not_to eq(0)
19
+ expect(debug_yml.keys.count).not_to eq(0)
19
20
 
20
21
  #Should not have same modules (at least for chrome)
21
22
  expect(release_yml["mods"].count).not_to eq(release_yml.keys.count)
22
23
  end
23
24
 
24
- it "can list modules specific to a platform and environment" do
25
- debug_mods = Flok::Platform.mods("chrome", "DEBUG")
26
- release_mods = Flok::Platform.mods("chrome", "RELEASE")
25
+ it "can list modules specific to an environment" do
26
+ config_yml = File.read("./spec/etc/lib/assets/config.yml")
27
+ Dir.chdir new_temp_dir do
28
+ File.write "config.yml", config_yml
29
+ ENV['FLOK_CONFIG'] = './config.yml'
27
30
 
28
- expect(debug_mods.count).not_to eq(0)
31
+ debug_mods = Flok::Platform.mods("DEBUG")
29
32
 
30
- #Should not have same modules (at least for chrome) in debug and release
31
- expect(debug_mods.count).not_to eq(release_mods.count)
33
+ expect(debug_mods).to include("hello")
34
+ ENV['FLOK_CONFIG'] = nil
35
+ end
32
36
  end
33
37
  end
@@ -22,4 +22,26 @@ RSpec.describe "lib/project" do
22
22
  end
23
23
  end
24
24
  end
25
+
26
+ it "Does contain a copy of the config.yml for the currently active platform in ./config/platforms/$PLATFORM/config.yml" do
27
+ platform = ENV['PLATFORM']
28
+
29
+ dir = new_temp_dir
30
+ Dir.chdir dir do
31
+ Flok::Project.create "test"
32
+ Dir.chdir "test" do
33
+ #Directory ./config/platforms/$PLATFORM should exist
34
+ expect(dirs).to include("config/platforms/#{platform}")
35
+
36
+ #File ./config/platforms/$PLATFORM/config.yml should exist
37
+ Dir.chdir "./config/platforms/#{platform}" do
38
+ expect(files).to include("config.yml")
39
+ end
40
+
41
+ #Files should match in config
42
+ platform_config_path = File.join(File.dirname(__FILE__), "../../../app/drivers/#{platform}/config.yml")
43
+ expect(File.read("./config/platforms/#{platform}/config.yml").strip).to eq(File.read(platform_config_path).strip)
44
+ end
45
+ end
46
+ end
25
47
  end
@@ -0,0 +1 @@
1
+ service_instance :test, :my_service
@@ -0,0 +1 @@
1
+ service_instance :blah, :my_service
@@ -0,0 +1,3 @@
1
+ service_instance :test, :my_service, {
2
+ hello: "23rntoheuh3nthoeunthn23th"
3
+ }
@@ -1,10 +1,26 @@
1
- service("test") do
2
- on_init %{
3
- test_service_var = true;
1
+ service :my_service do
2
+ on_wakeup %{
3
+ on_wakeup_called = true;
4
4
  }
5
5
 
6
- on_request %{
7
- //Services should allow for info, ep, and name
8
- test_service_request = [info, ep, ename]
6
+ on_sleep %{
7
+ on_sleep_called = true;
8
+ }
9
+
10
+ on_connect %{
11
+ on_connect_called_bp = bp;
12
+ }
13
+
14
+ on_disconnect %{
15
+ on_disconnect_called_bp = bp;
16
+ }
17
+
18
+ on "hello", %{
19
+ on_hello_called_bp = bp;
20
+ on_hello_called_params = JSON.stringify(params);
21
+ }
22
+
23
+ every 5.seconds, %{
24
+ on_every_5_sec_called = true;
9
25
  }
10
26
  end
@@ -0,0 +1,26 @@
1
+ service :my_service do
2
+ on_wakeup %{
3
+ on_wakeup_called = '#{@options[:hello]}';
4
+ }
5
+
6
+ on_sleep %{
7
+ on_sleep_called = true;
8
+ }
9
+
10
+ on_connect %{
11
+ on_connect_called_bp = bp;
12
+ }
13
+
14
+ on_disconnect %{
15
+ on_disconnect_called_bp = bp;
16
+ }
17
+
18
+ on "hello", %{
19
+ on_hello_called_bp = bp;
20
+ on_hello_called_params = JSON.stringify(params);
21
+ }
22
+
23
+ every 5.seconds, %{
24
+ on_every_5_sec_called = true;
25
+ }
26
+ end
@@ -0,0 +1,20 @@
1
+ service :test do
2
+ on_wakeup %{
3
+ test_service_var = true;
4
+ }
5
+
6
+ on_sleep %{
7
+ }
8
+
9
+ on_connect %{
10
+ }
11
+
12
+ on_disconnect %{
13
+ }
14
+
15
+ on_event "hello", %{
16
+ }
17
+
18
+ every 5.seconds, %{
19
+ }
20
+ end
@@ -4,13 +4,14 @@ require './spec/env/etc'
4
4
 
5
5
  RSpec.describe "lib/services_compiler" do
6
6
  #Return a v8 instance of a compiled js file
7
- def compile fn
7
+ def compile fn, config
8
8
  compiler = Flok::ServicesCompiler
9
9
  js_src(fn)
10
- js_res = compiler.compile(js_src(fn))
10
+ js_res = compiler.compile(js_src(fn), js_src(config))
11
11
  ctx = V8::Context.new
12
12
  ctx.eval js_res
13
- ctx
13
+
14
+ return ctx, js_res
14
15
  end
15
16
 
16
17
  #Get the source for a file in ./service_compiler/*.rb
@@ -20,22 +21,40 @@ RSpec.describe "lib/services_compiler" do
20
21
  end
21
22
  end
22
23
 
23
- it "Can call compile method and get on_init" do
24
- ctx = compile "service0"
25
-
26
- #The service defines a variable in on_init, this should be always accessible
27
- res = ctx.eval("test_service_var")
28
- expect(res).to eq(true)
24
+ it "Does fail to compile a controller with a non-existant type" do
25
+ expect { compile "service_bad_type" }.to raise_exception
29
26
  end
30
27
 
31
- it "Can call compile method and get on_request" do
32
- ctx = compile "service0"
28
+ it "Can call compile method and get a copy of all the functions" do
29
+ ctx, _ = compile "service0", "config0"
30
+
31
+ #on_wakeup
32
+ res = ctx.eval("test_on_wakeup")
33
+ expect(res).not_to eq(nil)
34
+
35
+ #on_sleep
36
+ res = ctx.eval("test_on_sleep")
37
+ expect(res).not_to eq(nil)
33
38
 
34
- #Should be able to call on_request generated request function
35
- ctx.eval('service_test_req({}, 0, "test")')
39
+ #on_connect
40
+ res = ctx.eval("test_on_connect");
41
+ expect(res).not_to eq(nil)
42
+
43
+ #on_disconnect
44
+ res = ctx.eval("test_on_disconnect")
45
+ expect(res).not_to eq(nil)
46
+
47
+ #on_event
48
+ res = ctx.eval("test_on_hello");
49
+ expect(res).not_to eq(nil)
50
+
51
+ #on_handle_timer_events
52
+ res = ctx.eval("test_handle_timer_events");
53
+ expect(res).not_to eq(nil)
54
+ end
36
55
 
37
- #That should have set a variable
38
- res = JSON.parse(ctx.eval("JSON.stringify(test_service_request)"))
39
- expect(res).to eq([{}, 0, "test"])
56
+ it "Can call compile method with options" do
57
+ ctx, js = compile "service1", "config2"
58
+ expect(js).to include("23rntoheuh3nthoeunthn23th");
40
59
  end
41
60
  end
@@ -0,0 +1,2 @@
1
+ //Test for merging in ./app/helpers/*.js folder for projects
2
+ data = {}
@@ -40,6 +40,13 @@ RSpec.describe "User compiler" do
40
40
  expect(actions).to eq(1)
41
41
  end
42
42
 
43
+ it "Can compile a controller and contain an __init__ function" do
44
+ ctx = compile "controller0"
45
+ actions = ctx.eval "ctable.my_controller.__init__"
46
+ expect(actions).not_to eq(nil)
47
+ end
48
+
49
+
43
50
  it "Can compile a controller with an action that contains an on_entry" do
44
51
  ctx = compile "controller0"
45
52
  on_entry = ctx.eval "ctable.my_controller.actions.my_action.on_entry"
@@ -52,7 +59,6 @@ RSpec.describe "User compiler" do
52
59
  expect(on_entry).to eq("my_controller")
53
60
  end
54
61
 
55
-
56
62
  it "Can compile a controller with an action that contains an event that responds to hello" do
57
63
  ctx = compile "controller0"
58
64
  hello_event_function = ctx.eval "ctable.my_controller.actions.my_action.handlers.hello"
@@ -0,0 +1,106 @@
1
+ Dir.chdir File.join File.dirname(__FILE__), '../../../'
2
+ require './spec/env/iface.rb'
3
+ require './spec/lib/helpers.rb'
4
+ require './spec/lib/io_extensions.rb'
5
+ require './spec/lib/rspec_extensions.rb'
6
+
7
+ RSpec.describe "iface:driver:persist" do
8
+ module_dep "persist"
9
+ include_context "iface:driver"
10
+
11
+ it "Can receive persist API messages without crashing" do
12
+ #Disk is scheduling class 2
13
+ @pipe.puts [[2, 3, "if_per_set", "my_ns", "my_key", "my_value"]].to_json
14
+ @pipe.puts [[2, 3, "if_per_get", "session", "my_ns", "my_key"]].to_json
15
+ @pipe.puts [[2, 2, "if_per_del", "my_ns", "my_key"]].to_json
16
+ @pipe.puts [[2, 1, "if_per_del_ns", "my_ns"]].to_json
17
+
18
+ #These are from the get requests
19
+ @pipe.readline_timeout
20
+
21
+ @pipe.puts [[0, 0, "ping"]].to_json;
22
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds([0, "pong"], 5.seconds)
23
+ end
24
+
25
+ it "Can set a persist, and then synchronously get" do
26
+ key = SecureRandom.hex
27
+ value = SecureRandom.hex
28
+
29
+ #Disk is scheduling class 2
30
+ @pipe.puts [[2, 3, "if_per_set", "my_ns", key, value]].to_json
31
+ restart_driver_but_persist
32
+ @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
33
+
34
+ #Expect a response
35
+ res = [2, "int_per_get_res", "session", value]
36
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
37
+ end
38
+
39
+
40
+ it "Can set a persist, and then asynchronously get" do
41
+ key = SecureRandom.hex
42
+ value = SecureRandom.hex
43
+
44
+ #Disk is scheduling class 2
45
+ @pipe.puts [[2, 3, "if_per_set", "my_ns", key, value]].to_json
46
+ restart_driver_but_persist
47
+ @pipe.puts [[2, 3, "if_per_get", "session", "my_ns", key]].to_json
48
+
49
+ #Expect a response
50
+ res = [2, "int_per_get_res", "session", value]
51
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
52
+ end
53
+
54
+ it "Can set a persist, delete the key, and then synchronously get" do
55
+ key = SecureRandom.hex
56
+ value = SecureRandom.hex
57
+
58
+ #Disk is scheduling class 2
59
+ @pipe.puts [[2, 3, "if_per_set", "my_ns", key, value]].to_json
60
+ @pipe.puts [[2, 2, "if_per_del", "my_ns", key]].to_json
61
+ restart_driver_but_persist
62
+ @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
63
+
64
+ #Expect a response
65
+ res = [2, "int_per_get_res", "session", nil]
66
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
67
+ end
68
+
69
+ it "Can set two persists, delete one key, and then synchronously get" do
70
+ key = SecureRandom.hex
71
+ key2 = SecureRandom.hex
72
+ value = SecureRandom.hex
73
+ value2 = SecureRandom.hex
74
+
75
+ #Disk is scheduling class 2
76
+ @pipe.puts [[2, 3, "if_per_set", "my_ns", key, value]].to_json
77
+ @pipe.puts [[2, 3, "if_per_set", "my_ns", key2, value2]].to_json
78
+ @pipe.puts [[2, 2, "if_per_del", "my_ns", key]].to_json
79
+ restart_driver_but_persist
80
+ @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
81
+ @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key2]].to_json
82
+
83
+ #Results for first key
84
+ res = [2, "int_per_get_res", "session", nil]
85
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
86
+
87
+ #Expect a response
88
+ res = [2, "int_per_get_res", "session", value2]
89
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
90
+ end
91
+
92
+ it "Can set a persist, delete the key via ns, and then synchronously get" do
93
+ key = SecureRandom.hex
94
+ value = SecureRandom.hex
95
+
96
+ #Disk is scheduling class 2
97
+ @pipe.puts [[2, 3, "if_per_set", "my_ns", key, value]].to_json
98
+ @pipe.puts [[2, 1, "if_per_del_ns", "my_ns"]].to_json
99
+ restart_driver_but_persist
100
+ @pipe.puts [[0, 3, "if_per_get", "session", "my_ns", key]].to_json
101
+
102
+ #Expect a response
103
+ res = [2, "int_per_get_res", "session", nil]
104
+ expect(@pipe).to readline_and_equal_json_x_within_y_seconds(res, 5.seconds)
105
+ end
106
+ end
@@ -28,4 +28,9 @@ RSpec.describe "iface:driver:pipe_spec" do
28
28
 
29
29
  expect(pid).to die_within(6.seconds)
30
30
  end
31
+
32
+ it "does have the ability to receive a RESTART command" do
33
+ @pipe.puts "RESTART"
34
+ expect(@pipe).to readline_and_equal_x_within_y_seconds("RESTART OK", 5.seconds)
35
+ end
31
36
  end
@@ -70,7 +70,8 @@ RSpec.describe "iface:kern:ping_spec" do
70
70
  "net" => 1,
71
71
  "disk" => 2,
72
72
  "cpu" => 3,
73
- "gpu" => 4
73
+ "gpu" => 4,
74
+ "async" => 5
74
75
  }
75
76
 
76
77
  queue_name_to_index.each do |name, index|
@@ -78,7 +79,7 @@ RSpec.describe "iface:kern:ping_spec" do
78
79
  #Don't redo last one because it's part of the first term (queue_name_b)
79
80
  unless index == queue_name_to_index.count-1
80
81
  queue_name_a = name
81
- queue_name_b = @last_queue_name || "gpu"
82
+ queue_name_b = @last_queue_name || "async"
82
83
  index_a = index
83
84
  index_b = queue_name_to_index[queue_name_b]
84
85
  @pipe.puts [1, "ping3", queue_name_a, 1, "ping3", queue_name_a, 1, "ping3", queue_name_b].to_json
@@ -104,7 +105,7 @@ RSpec.describe "iface:kern:ping_spec" do
104
105
  queue_name_to_index.each do |name, index|
105
106
  it "supports ping-over-commit" do
106
107
  #Main queue always queues all
107
- if name != "main"
108
+ if name != "main" and name != "async" #main and async don't have scheduling
108
109
  @pipe.puts ([1, "ping4", name]*6).to_json
109
110
  expect(@pipe).to readline_and_equal_json_x_within_y_seconds([[index, *[0, "pong4"]*5]], 6.seconds)
110
111
  @pipe.puts ([1, "ping4", name]).to_json
File without changes
@@ -0,0 +1,24 @@
1
+ service :my_service do
2
+ on_wakeup %{
3
+ on_wakeup_called = true;
4
+ }
5
+
6
+ on_sleep %{
7
+ on_sleep_called = true;
8
+ }
9
+
10
+ on_connect %{
11
+ on_connect_called = true;
12
+ }
13
+
14
+ on_disconnect %{
15
+ on_disconnect_called = true;
16
+ }
17
+
18
+ every 1.seconds, %{
19
+ for (var i = 0; i < Object.keys(sessions).length; ++i) {
20
+ var bp = Object.keys(sessions)[i];
21
+ int_event(bp, "ping", {});
22
+ }
23
+ }
24
+ end