flok 0.0.36 → 0.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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