Browse Source

v1 - no ets, lists only

221V 3 years ago
parent
commit
bfa030d608
11 changed files with 226 additions and 0 deletions
  1. 2 0
      .gitignore
  2. 2 0
      Emakefile
  3. 14 0
      Makefile
  4. 30 0
      README.md
  5. 10 0
      apps/myapp/ebin/myapp.app
  6. 12 0
      apps/myapp/src/myapp.erl
  7. 99 0
      apps/myapp/src/myapp_events.erl
  8. 19 0
      apps/myapp/src/myapp_sup.erl
  9. 26 0
      apps/myapp/src/test.erl
  10. 3 0
      sys.config
  11. 9 0
      vm.args

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+/apps/myapp/ebin/*.beam
+

+ 2 - 0
Emakefile

@@ -0,0 +1,2 @@
+
+{"apps/myapp/src/*", [debug_info, {outdir, "apps/myapp/ebin"}]}.

+ 14 - 0
Makefile

@@ -0,0 +1,14 @@
+
+default: compile
+
+clean:
+	rm apps/myapp/ebin/*.beam
+
+compile:
+	ERL_LIBS="apps:deps" erl -make;
+
+start:
+	ERL_LIBS="apps:deps" erl +pc unicode -args_file vm.args -config sys.config -eval 'application:start(myapp)'
+
+
+.PHONY: compile clean start

+ 30 - 0
README.md

@@ -40,3 +40,33 @@
 
 Задание можно полностью не сделать. Важен подход и оформление кода.  
 
+---
+
+```
+$ make
+$ make start
+ERL_LIBS="apps:deps" erl +pc unicode -args_file vm.args -config sys.config -eval 'application:start(myapp)'
+Erlang/OTP 23 [erts-11.2.2.4] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:5] [hipe]
+
+Eshell V11.2.2.4  (abort with ^G)
+(myapp@127.0.0.1)1> test:test().
+ok
+(myapp@127.0.0.1)2> update: "12" 12
+deleted: "9" 9
+deleted: "14" 14
+tick: "1" 1
+tick: "3" 3
+tick: "5" 5
+tick: "7" 7
+tick: "2" 2
+tick: "4" 4
+tick: "11" 11
+tick: "6" 6
+tick: "13" 13
+tick: "8" 8
+tick: "15" 15
+tick: "10" 10
+tick: "12" 12
+
+```
+

+ 10 - 0
apps/myapp/ebin/myapp.app

@@ -0,0 +1,10 @@
+{application, myapp,
+ [
+  {description, "test erlang application"},
+  {vsn, "0.0.1"},
+  {registered, [myapp_sup]},
+  {applications, [kernel, stdlib]},
+  {modules, [myapp, myapp_sup, myapp_events, test]},
+  {mod, { myapp, []}},
+  {env, []}
+ ]}.

+ 12 - 0
apps/myapp/src/myapp.erl

@@ -0,0 +1,12 @@
+-module(myapp).
+-behaviour(application).
+
+-export([start/2, stop/1]).
+
+
+start(_Type, _Args) ->
+  myapp_sup:start_link().
+
+stop(_State) ->
+  ok.
+

+ 99 - 0
apps/myapp/src/myapp_events.erl

@@ -0,0 +1,99 @@
+-module(myapp_events).
+-behaviour(gen_server).
+
+-export([start_link/0]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+-export([add_task/4, delete_task/2]).
+
+
+-define(IS_STRING(S), (is_list(S) andalso S /= [] andalso is_integer(hd(S)))).
+
+
+add_task(Task_Id, Proc_Id, Type, Time)
+when ?IS_STRING(Task_Id), is_integer(Proc_Id), ((Type =:= static) orelse (Type =:= dynamic)), is_integer(Time) ->
+  Time2 = case Type of
+    dynamic ->
+      erlang:system_time(second) + Time; % Timestamp_Now + Time
+    _ ->
+      % static
+      Time
+  end,
+  gen_server:cast(?MODULE, {add_task, {Task_Id, Proc_Id, Time2}}),
+  ok.
+
+delete_task(Task_Id, Proc_Id)
+when ?IS_STRING(Task_Id), is_integer(Proc_Id) ->
+  gen_server:cast(?MODULE, {delete_task, {Task_Id, Proc_Id}}),
+  ok.
+
+
+start_link() ->
+  gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+
+init([]) ->
+  erlang:send_after(100, self(), check_time_process),
+  State = [],
+  {ok, State}.
+
+
+handle_call(_Req, _From, State) ->
+  {reply, not_handled, State}.
+
+
+handle_cast({add_task, {Task_Id, Proc_Id, _Time}=V}, State) ->
+  State2 = lists:filter(fun({Task_Id0, Proc_Id0, _Time0}) ->
+    if Task_Id =:= Task_Id0 andalso Proc_Id =:= Proc_Id0 ->
+        io:format("update: ~p ~p~n", [Task_Id0, Proc_Id0]),
+        false;
+      true -> true
+    end
+    end, State),
+  {noreply, [V|State2]};
+
+
+handle_cast({delete_task, {Task_Id, Proc_Id}}, State) ->
+  State2 = lists:filter(fun({Task_Id0, Proc_Id0, _Time}) ->
+    if Task_Id =:= Task_Id0 andalso Proc_Id =:= Proc_Id0 ->
+        io:format("deleted: ~p ~p~n", [Task_Id0, Proc_Id0]),
+        false;
+      true -> true
+    end
+    end, State),
+  {noreply, State2};
+
+
+handle_cast(_Req, State) ->
+  {noreply, State}.
+
+
+handle_info(check_time_process, []) ->
+  erlang:send_after(1000, self(), check_time_process),
+  {noreply, []};
+handle_info(check_time_process, State) ->
+  Timestamp_Now = erlang:system_time(second),
+  State2 = lists:filtermap(fun({Task_Id0, Proc_Id0, Time0}=V) ->
+    if Time0 =< Timestamp_Now ->
+        % send_to_rabbitmq({call_timer, Proc_Id0, Task_Id0}),
+        io:format("tick: ~p ~p~n", [Task_Id0, Proc_Id0]),
+        false;
+      true -> {true, V}
+    end
+    end, State),
+  
+  erlang:send_after(1000, self(), check_time_process),
+  {noreply, State2};
+
+
+handle_info(_Request, State) ->
+  {noreply, State}.
+
+
+terminate(_Reason, _State) ->
+  ok.
+
+code_change(_OldVsn, State, _Extra) -> 
+  {ok, State}.
+
+

+ 19 - 0
apps/myapp/src/myapp_sup.erl

@@ -0,0 +1,19 @@
+-module(myapp_sup).
+-behaviour(supervisor).
+
+-export([start_link/0, init/1]).
+
+
+start_link() ->
+  supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init(_Args) ->
+  Procs = [
+    #{id => worker_1,
+      start => {myapp_events, start_link, []},
+      restart => permanent,
+      type => worker,
+      modules => [myapp_events] }],
+  
+  {ok, { #{strategy => one_for_one, intensity => 10, period => 100}, Procs}}.
+

+ 26 - 0
apps/myapp/src/test.erl

@@ -0,0 +1,26 @@
+-module(test).
+
+-export([test/0]).
+
+test() ->
+  Timestamp_Now = erlang:system_time(second),
+  L = lists:seq(1, 15),
+  [myapp_events:add_task(integer_to_list(X), X, dynamic, X + 10) || X <- L, X rem 2 =:= 0],
+  [myapp_events:add_task(integer_to_list(X), X, static, Timestamp_Now + X + 5) || X <- L, X rem 2 =:= 1],
+  
+  spawn(fun() ->
+    timer:sleep(3000),
+    
+    myapp_events:add_task("12", 12, dynamic, 50),
+    myapp_events:add_task("12", 13, static, Timestamp_Now + 8000),
+    
+    myapp_events:delete_task("9", 9),
+    myapp_events:delete_task("14", 14),
+    
+    ok
+  end),
+  
+  ok.
+
+
+

+ 3 - 0
sys.config

@@ -0,0 +1,3 @@
+[
+].
+

+ 9 - 0
vm.args

@@ -0,0 +1,9 @@
+-name myapp@127.0.0.1
+-setcookie H2jbqXqNULBxXP5y6
++pc unicode
++K true
++A 5
+-env ERL_MAX_PORTS 4096
+-env ERL_FULLSWEEP_AFTER 10
+-env ERL_EPMD_ADDRESS 127.0.0.1
+-kernel inet_dist_use_interface {127,0,0,1}