Skip to content

Commit

Permalink
update deps and add CI testing
Browse files Browse the repository at this point in the history
  • Loading branch information
tsloughter committed Nov 10, 2024
1 parent a9e69aa commit dae2593
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 25 deletions.
61 changes: 61 additions & 0 deletions .github/workflows/ct.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: CI

on:
pull_request:
branches:
- 'main'
push:
branches:
- 'main'

jobs:
build:
name: Test on OTP ${{ matrix.otp_version }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
otp_version: ['27']
rebar3_version: ['3.24']
os: [ubuntu-latest]
env:
OTP_VERSION: ${{ matrix.otp_version }}
steps:
- uses: actions/checkout@v4
- name: Run Collector
run: docker compose up -d
- uses: erlef/setup-beam@v1
with:
otp-version: ${{ matrix.otp_version }}
rebar3-version: ${{ matrix.rebar3_version }}
- uses: actions/cache@v4
name: Cache
with:
path: |
_build
key: ${{ runner.os }}-build-${{ matrix.otp_version }}-${{ hashFiles(format('rebar.lock')) }}-1
restore-keys: |
${{ runner.os }}-build-${{ matrix.otp_version }}-1-
- name: Compile
run: rebar3 compile
- name: Common Test tests
run: rebar3 ct --cover

- name: Publish Test Report
uses: mikepenz/action-junit-report@v2
if: always() # always run even if the previous step fails
with:
report_paths: '_build/test/logs/*/junit_report.xml'

- name: XRef
run: rebar3 xref
- name: Covertool
if: ${{ always() }}
run: rebar3 covertool generate
- uses: codecov/codecov-action@v2
if: ${{ always() }}
with:
file: _build/test/covertool/erleans_provider_pgo.covertool.xml
env_vars: OTP_VERSION

- name: Dialyzer
run: rebar3 dialyzer
47 changes: 44 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,48 @@ Erleans Postgres Persistence Provider

[Erleans](https://github.com/erleans/erleans) Persistence Provider backed by Postgres with library [pgo](https://github.com/erleans/pgo).

Build
-----
# Usage

$ rebar3 compile
Configure your Grains to use the Postgres provider and the database to use for
the `pgo` pool that backs the provider in `sys.config`:

```
[{erleans, [{providers, #{pgo => #{module => erleans_provider_pgo,
args => #{pool_size => 10,
host => "127.0.0.1",
database => "test",
user => "test",
password=> "test"}
}}},
{default_provider, pgo}]},
```

Now you can run a grain and save it to Postgres:

```
> Grain1 = erleans:get_grain(test_grain, <<"grain1">>).
> test_grain:activated_counter(Grain1).
> test_grain:save(Grain1).
```

```
test=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------------+-------+-------
public | erleans_grains | table | test
test=# select * from erleans_grains;
grain_id | grain_type | grain_ref_hash | grain_etag |
grain_state
| change_time
----------------------------+------------+----------------+------------+--------
--------------------------------------------------------------------------------
------------------------------------------------+----------------------------
\x836d00000006677261696e31 | test_grain | 99587447 | 64845372 | \x83740
000000377116163746976617465645f636f756e7465726101771364656163746976617465645f636
f756e7465726101770c63616c6c5f636f756e7465726102 | 2024-11-10 10:25:31.303615
(1 row)
```


14 changes: 14 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
services:
postgres:
image: cimg/postgres:14.2
restart: always
ports:
- 5432:5432
tmpfs:
- /var/lib/newpostgres/data
command: -c fsync=off -c full_page_writes=off
environment:
- POSTGRES_USER=test
- POSTGRES_DB=test
- POSTGRES_PASSWORD=test
- POSTGRES_HOST_AUTH_METHOD=scram-sha-256
22 changes: 15 additions & 7 deletions rebar.config
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
{erl_opts, [debug_info]}.
{deps, [{pgo, "~> 0.11.0"}]}.
{deps, [pgo,
eql]}.

{shell, [
% {config, "config/sys.config"},
{apps, [erleans_provider_pgo]}
]}.
{profiles, [{test, [{erl_opts, [nowarn_export_all]},
{deps, [{erleans, {git, "https://github.com/erleans/erleans", {branch, "global-refactor"}}}]}]}]}.

{profiles, [{test, [{deps, [erleans]},
{erl_opts, [nowarn_export_all]}]}]}.
{ct_opts, [{ct_hooks, [cth_surefire]},
{sys_config, "test/sys.config"}]}.

{shell, [{apps, [erleans_provider_pgo]}]}.

{project_plugins, [covertool]}.

{cover_enabled, true}.
{cover_opts, [verbose]}.
{cover_export_enabled, true}.
{covertool, [{coverdata_files, ["ct.coverdata"]}]}.
22 changes: 15 additions & 7 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
{"1.1.0",
{"1.2.0",
[{<<"backoff">>,{pkg,<<"backoff">>,<<"1.1.6">>},1},
{<<"pg_types">>,{pkg,<<"pg_types">>,<<"0.2.0">>},1},
{<<"pgo">>,{pkg,<<"pgo">>,<<"0.11.0">>},0},
{<<"telemetry">>,{pkg,<<"telemetry">>,<<"0.4.1">>},1}]}.
{<<"eql">>,{pkg,<<"eql">>,<<"0.2.0">>},0},
{<<"opentelemetry_api">>,{pkg,<<"opentelemetry_api">>,<<"1.4.0">>},1},
{<<"pg_types">>,{pkg,<<"pg_types">>,<<"0.4.0">>},1},
{<<"pgo">>,{pkg,<<"pgo">>,<<"0.14.0">>},0}]}.
[
{pkg_hash,[
{<<"backoff">>, <<"83B72ED2108BA1EE8F7D1C22E0B4A00CFE3593A67DBC792799E8CCE9F42F796B">>},
{<<"pg_types">>, <<"B73A0409CB94183226547EDF10793F6B3AD00E098B8D70354EF3886C0F95F2F6">>},
{<<"pgo">>, <<"66D5608192BF36511F72696DCBB73A8C8D44210E17DDACD15C18F9511E49549B">>},
{<<"telemetry">>, <<"AE2718484892448A24470E6AA341BC847C3277BFB8D4E9289F7474D752C09C7F">>}]}
{<<"eql">>, <<"598ABC19A1CF6AFB8EF89FFEA869F43BAEBB1CEC3260DD5065112FEE7D8CE3E2">>},
{<<"opentelemetry_api">>, <<"63CA1742F92F00059298F478048DFB826F4B20D49534493D6919A0DB39B6DB04">>},
{<<"pg_types">>, <<"3CE365C92903C5BB59C0D56382D842C8C610C1B6F165E20C4B652C96FA7E9C14">>},
{<<"pgo">>, <<"F53711D103D7565DB6FC6061FCF4FF1007AB39892439BE1BB02D9F686D7E6663">>}]},
{pkg_hash_ext,[
{<<"backoff">>, <<"CF0CFFF8995FB20562F822E5CC47D8CCF664C5ECDC26A684CBE85C225F9D7C39">>},
{<<"eql">>, <<"513BE6B36EE86E8292B2B7475C257ABB66CED5AAD40CBF7AD21E233D0A3BF51D">>},
{<<"opentelemetry_api">>, <<"3DFBBFAA2C2ED3121C5C483162836C4F9027DEF469C41578AF5EF32589FCFC58">>},
{<<"pg_types">>, <<"B02EFA785CAECECF9702C681C80A9CA12A39F9161A846CE17B01FB20AEEED7EB">>},
{<<"pgo">>, <<"71016C22599936E042DC0012EE4589D24C71427D266292F775EBF201D97DF9C9">>}]}
].
3 changes: 2 additions & 1 deletion src/erleans_provider_pgo.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
{applications,
[kernel,
stdlib,
pgo
pgo,
eql
]},
{env,[]},
{modules, []},
Expand Down
15 changes: 8 additions & 7 deletions src/erleans_provider_pgo.erl
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ all(Type, ProviderName) ->
read(Type, ProviderName, Id) ->
do(ProviderName, fun() ->
case read_(Id, Type, erlang:phash2({Id, Type})) of
{ok, {_, _, ETag, State}} ->
{value, {_, _, ETag, State}} ->
{ok, binary_to_term(State), ETag};
error ->
false ->
not_found
end
end).
Expand Down Expand Up @@ -111,11 +111,12 @@ read_(Id, Type, RefHash) ->
#{command := select, rows := Rows} = pgo:query(Q, [RefHash, atom_to_binary(Type, unicode)]),
IdBin = term_to_binary(Id),
TypeBin = atom_to_binary(Type, utf8),
ec_lists:find(fun({RowId, RowType, _, _}) when IdBin =:= RowId
, TypeBin =:= RowType-> true;
(_) ->
false
end, Rows).
lists:search(fun({RowId, RowType, _, _}) when IdBin =:= RowId
, TypeBin =:= RowType ->
true;
(_) ->
false
end, Rows).

delete_(Id, Type, RefHash) ->
Q = query(delete),
Expand Down
17 changes: 17 additions & 0 deletions test/erleans_provider_pgo_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,22 @@
all() ->
[basic_insert].

init_per_suite(Config) ->
{ok, _} = application:ensure_all_started(pgo),
{ok, _} =
application:ensure_all_started(erleans_provider_pgo),
{ok, _} = application:ensure_all_started(erleans),
Config.

end_per_suite(_Config) ->
application:stop(erleans),
application:stop(erleans_provider_pgo),
application:stop(pgo),
ok.

basic_insert(_Config) ->
Grain1 = erleans:get_grain(test_grain, <<"grain1">>),
test_grain:activated_counter(Grain1),
test_grain:save(Grain1),

ok.
18 changes: 18 additions & 0 deletions test/sys.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
%% -*- erlang -*-
[{erleans, [{grain_provider, [{test_grain, pgo}]},

{providers, #{pgo => #{module => erleans_provider_pgo,
args => #{pool_size => 10,
host => "127.0.0.1",
database => "test",
user => "test",
password=> "test"}
}}},

{default_provider, pgo}]},

{kernel, [{logger_level, debug},
{logger, [{filters, log, [{no_progress, {fun logger_filters:progress/2, stop}}]},
{handler, default, logger_std_h,
#{formatter => {logger_formatter, #{template => [time," ", file,":",line," ",level,": ",msg,"\n"]}}}}]}]}
].
80 changes: 80 additions & 0 deletions test/test_grain.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
%%% ---------------------------------------------------------------------------
%%% @author Tristan Sloughter <tristan.sloughter@spacetimeinsight.com>
%%% @copyright 2016 Space-Time Insight <tristan.sloughter@spacetimeinsight.com>
%%%
%%% @doc A test grain that increments a counter every time it is activated.
%%% @end
%%% ---------------------------------------------------------------------------
-module(test_grain).

-behaviour(erleans_grain).

-export([placement/0,
provider/0,
save/1,
node/1,
deactivated_counter/1,
activated_counter/1,
call_counter/1]).

-export([state/1,
activate/2,
handle_call/3,
handle_cast/2,
deactivate/1]).

placement() ->
prefer_local.

provider() ->
default.

deactivated_counter(Ref) ->
erleans_grain:call(Ref, deactivated_counter).

activated_counter(Ref) ->
erleans_grain:call(Ref, activated_counter).

call_counter(Ref) ->
erleans_grain:call(Ref, call_counter).

save(Ref) ->
erleans_grain:call(Ref, save).

node(Ref) ->
erleans_grain:call(Ref, node).

state(_) ->
#{activated_counter => 0,
deactivated_counter => 0,
call_counter => 0}.

activate(_, State=#{activated_counter := Counter}) ->
{ok, State#{activated_counter => Counter+1}, #{}}.

handle_call(call_counter, From, State=#{call_counter := CallCounter}) ->
{ok, State#{call_counter => CallCounter+1}, [{reply, From, {ok, CallCounter}}]};
handle_call(node, From, State=#{call_counter := CallCounter}) ->
{ok, State#{call_counter => CallCounter+1}, [{reply, From, {ok, node()}}]};
handle_call(deactivated_counter, From, State=#{deactivated_counter := Counter,
call_counter := CallCounter}) ->
{ok, State#{call_counter => CallCounter+1}, [{reply, From, {ok, Counter}}]};
handle_call(deactivated_counter, From, State=#{call_counter := CallCounter}) ->
{ok, State#{call_counter => CallCounter+1}, [{reply, From, {ok, 0}}]};
handle_call(activated_counter, From, State=#{activated_counter := Counter,
call_counter := CallCounter}) ->
{ok, State#{call_counter => CallCounter+1}, [{reply, From, {ok, Counter}}]};
handle_call(activated_counter, From, State=#{call_counter := CallCounter}) ->
{ok, State#{call_counter => CallCounter+1}, [{reply, From, {ok, 0}}]};
handle_call(save, From, State=#{call_counter := CallCounter}) ->
{ok, State#{call_counter => CallCounter+1}, [{reply, From, ok}, save_state]}.

handle_cast(_, State) ->
{ok, State}.

deactivate(State=#{deactivated_counter := D}) ->
{save_state, State#{deactivated_counter => D+1}}.

%%%===================================================================
%%% Internal functions
%%%===================================================================

0 comments on commit dae2593

Please sign in to comment.