Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 67
Rovio Ad Counter Union Product Ads Riot Ad Counter Contracts Riot Ads Riot Ad Counter 68
Increment Rovio Ad Counter Read Remove ≥ 50,000 Rovio Ads Rovio Ad Counter Ads Union Product Filter Ads Contracts Riot Ad Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter 69
Ads Ads Union Product Filter Ads With Contracts Contracts Lasp Operation Contracts User-Maintained CRDT 70
Read Ads Ads Product Filter Ads With Contracts Contracts Lasp Operation Contracts 71
Counter1 Counter2 Counter3 Read Counter1 Counter2 Counter3 Ads Ads Filter With Contracts Contracts Counter1 Counter2 Counter3 Lasp Operation User-Maintained CRDT Counter1 Counter2 Counter3 Lasp-Maintained CRDT 72
Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 73
Increment Rovio Ad Counter Read Remove ≥ 50,000 Rovio Ads Rovio Ad Counter Ads Union Product Ads Contracts Riot Ad Counter Lasp Operation Contracts Riot Ads 74
Counter1 Counter2 Counter3 Read Remove Read 50,000 Rovio Ads Counter1 Counter2 Counter3 Ads Ads Union Product Filter Ads With Contracts Contracts Counter1 Counter2 Counter3 Lasp Operation Contracts Riot Ads User-Maintained CRDT Counter1 Counter2 Counter3 Lasp-Maintained CRDT 75
INFORMATION FLOW: MONOTONIC METADATA TO PREVENT DUPLICATE PROPAGATION 76
AD COUNTER EXAMPLE CODE 77
%% @doc Client process; standard recursive looping server. client(Id, AdsWithContracts, PreviousValue) -> receive view_ad -> %% Get current ad list. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts, PreviousValue), AdList = riak_dt_orset:value(AdList0), case length(AdList) of 0 -> %% No advertisements left to display; ignore %% message. client(Id, AdsWithContracts, AdList0); _ -> %% Select a random advertisement from the list of %% active advertisements. {#ad{counter=Ad}, _} = lists:nth( random:uniform(length(AdList)), AdList), %% Increment it. {ok, _} = lasp:update(Ad, increment, Id), lager:info("Incremented ad counter: ~p", [Ad]), client(Id, AdsWithContracts, AdList0) end end.
%% @doc Server functions for the advertisement counter. After 5 views, %% disable the advertisement. %% server({#ad{counter=Counter}=Ad, _}, Ads) -> %% Blocking threshold read for 5 advertisement impressions. {ok, _} = lasp:read(Counter, 5), %% Remove the advertisement. {ok, _} = lasp:update(Ads, {remove, Ad}, Ad), lager:info("Removing ad: ~p", [Ad]).
%% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),
%% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),
%% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),
%% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),
%% Generate a series of unique identifiers. %% Compute the Cartesian product of both ads and contracts. RovioAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), {ok, AdsContracts} = lasp:declare(?SET), lager:info("Rovio Ad Identifiers are: ~p", [RovioAdIds]), ok = lasp:product(Ads, Contracts, AdsContracts), TriforkAdIds = lists:map(fun(_) -> druuid:v4() end, lists:seq(1, 10)), %% Filter items by join on item it. lager:info("Trifork Ad Identifiers are: ~p", [TriforkAdIds]), {ok, AdsWithContracts} = lasp:declare(?SET), FilterFun = fun({#ad{id=Id1}, #contract{id=Id2}}) -> Ids = RovioAdIds ++ TriforkAdIds, Id1 =:= Id2 lager:info("Ad Identifiers are: ~p", [Ids]), end, ok = lasp:filter(AdsContracts, FilterFun, AdsWithContracts), %% Generate Rovio's advertisements. {ok, RovioAds} = lasp:declare(?SET), %% Launch a series of client processes, each of which is responsible lists:map(fun(Id) -> %% for displaying a particular advertisement. %% Generate a G-Counter. {ok, CounterId} = lasp:declare(?COUNTER), %% Generate a OR-set for tracking clients. %% Add it to the advertisement set. {ok, Clients} = lasp:declare(?SET), {ok, _} = lasp:update(RovioAds, {add, #ad{id=Id, counter=CounterId}}, %% Each client takes the full list of ads when it starts, and reads undefined) %% from the variable store. lists:map(fun(Id) -> end, RovioAdIds), ClientPid = spawn_link(?MODULE, client, [Id, AdsWithContracts, undefined]), %% Generate Trifork's advertisements. {ok, _} = lasp:update(Clients, {ok, TriforkAds} = lasp:declare(?SET), {add, ClientPid}, lists:map(fun(Id) -> undefined) %% Generate a G-Counter. end, lists:seq(1,5)), {ok, CounterId} = lasp:declare(?COUNTER), %% Add it to the advertisement set. %% Launch a server process for each advertisement, which will block {ok, _} = lasp:update(TriforkAds, %% until the advertisement should be disabled. {add, #ad{id=Id, counter=CounterId}}, undefined) %% Create a OR-set for the server list. {ok, Servers} = lasp:declare(?SET), end, TriforkAdIds), %% Get the current advertisement list. %% Union ads. {ok, {_, _, AdList0}} = lasp:read(AdsWithContracts), {ok, Ads} = lasp:declare(?SET), AdList = riak_dt_orset:value(AdList0), ok = lasp:union(RovioAds, TriforkAds, Ads), %% For each advertisement, launch one server for tracking it's %% For each identifier, generate a contract. %% impressions and wait to disable. {ok, Contracts} = lasp:declare(?SET), lists:map(fun(Ad) -> lists:map(fun(Id) -> ServerPid = spawn_link(?MODULE, server, [Ad, Ads]), {ok, _} = lasp:update(Contracts, {ok, _} = lasp:update(Servers, {add, #contract{id=Id}}, {add, ServerPid}, undefined) undefined) end, Ids), end, AdList),
AD COUNTER DISTRIBUTION 85
Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 86
Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 87
Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 88
Increment Rovio Ad Counter1 Counter2 Counter3 Counter Read Remove Read ≥ 50,000 Rovio Ads Rovio Ad Counter1 Counter2 Counter3 Counter Ads Ads Union Product Filter Ads With Contracts Contracts Riot Ad Counter1 Counter2 Counter3 Counter Lasp Operation Contracts Riot Ads User-Maintained CRDT Riot Ad Counter1 Counter2 Counter3 Counter Lasp-Maintained CRDT 89
DISTRIBUTION BOUNDARIES: ARBITRARY ALLOWS COMPOSITION OF ENTIRE SYSTEM 90
MATERIALIZED VIEWS 91
MATERIALIZED VIEWS: INCREMENTALLY UPDATING, DELTA PROPAGATION SCHEMA BASED OR DYNAMIC; 2I IN RIAK 92
DATABASE AS STREAM OF UPDATES 93
K1 K2 K3 K1 K2 Riak 94
RS1 K1 K2 K3 K1 K2 RS2 Riak RS3 95
K1 K1 RS1 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 96
K1 K1 N1 N3 N2 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 97
COMPOSE PROGRAMS 98
K1 K1 N1 N3 N2 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 Lasp Stream Processor Template 99
K1 K1 N1 N3 N2 K1 K2 K3 K1 K2 K2 K2 RS2 Riak K3 RS3 Lasp All Objects Program Lasp Stream Processor Template 100
Recommend
More recommend