_site/cover/pgmp_mm_bootstrap.COVER.html

1 %% Copyright (c) 2022 Peter Morgan <peter.james.morgan@gmail.com>
2 %%
3 %% Licensed under the Apache License, Version 2.0 (the "License");
4 %% you may not use this file except in compliance with the License.
5 %% You may obtain a copy of the License at
6 %%
7 %% http://www.apache.org/licenses/LICENSE-2.0
8 %%
9 %% Unless required by applicable law or agreed to in writing, software
10 %% distributed under the License is distributed on an "AS IS" BASIS,
11 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 %% See the License for the specific language governing permissions and
13 %% limitations under the License.
14
15
16 -module(pgmp_mm_bootstrap).
17
18
19 -export([callback_mode/0]).
20 -export([handle_event/4]).
21 -export([terminate/3]).
22 -import(pgmp_codec, [marshal/2]).
23 -import(pgmp_codec, [size_inclusive/1]).
24 -import(pgmp_statem, [nei/1]).
25 -include_lib("kernel/include/logger.hrl").
26
27
28 callback_mode() ->
29 132 [handle_event_function, state_enter].
30
31
32 terminate(Reason, State, Data) ->
33
:-(
pgmp_mm_common:terminate(Reason, State, Data).
34
35
36 handle_event({call, _}, {request, _}, unready, Data) ->
37 61 {next_state, starting, Data, [postpone, nei(startup)]};
38
39 handle_event({call, From},
40 {request, _},
41 startup_failure,
42 #{errors := Errors}) ->
43
:-(
{keep_state_and_data, {reply, From, [Errors]}};
44
45 handle_event({call, _}, {request, _}, _, _) ->
46 122 {keep_state_and_data, postpone};
47
48 handle_event(internal, peer, _, Data) ->
49 66 case pgmp_sup:get_child(hd(get('$ancestors')), socket) of
50 {_, PID, worker, _} when is_pid(PID) ->
51 66 {keep_state,
52 Data#{socket => PID},
53 nei(eager_startup_for_replication)};
54
55 {_, _, _, _} = Reason ->
56
:-(
{stop, Reason};
57
58 false ->
59
:-(
{stop, peer_not_found}
60 end;
61
62 handle_event(internal,
63 join = EventName,
64 _,
65 #{requests := Requests,
66 config := #{scope := Scope,
67 group := Group} = Config} = Data) ->
68 61 pg:join(Scope, Group, self()),
69 61 {keep_state,
70 Data#{requests := pgmp_connection:join(
71 #{group => Group,
72 server_ref => pgmp_connection:server_ref(Config),
73 requests => Requests})},
74 nei({telemetry,
75 EventName,
76 #{count => 1},
77 #{group => Group}})};
78
79 handle_event(internal, join, _, #{config := #{}}) ->
80 5 keep_state_and_data;
81
82 handle_event(internal,
83 types_when_ready,
84 _,
85 #{requests := Requests, config := Config} = Data) ->
86 66 {keep_state,
87 Data#{requests := pgmp_types:when_ready(
88 #{requests => Requests,
89 server_ref => pgmp_types:server_ref(Config)})}};
90
91 handle_event(internal,
92 eager_startup_for_replication,
93 _,
94 #{config := #{replication := <<"false">>}}) ->
95 61 keep_state_and_data;
96
97 handle_event(internal,
98 eager_startup_for_replication,
99 _,
100 _) ->
101 5 {keep_state_and_data, nei(startup)};
102
103 handle_event(internal, startup, _, _) ->
104 66 {keep_state_and_data,
105 nei({send, size_inclusive([marshal(int32, 80877103)])})};
106
107 handle_event(internal, {recv, {ssl, false}}, _, _) ->
108
:-(
{keep_state_and_data, nei({startup, #{}})};
109
110 handle_event(internal, {recv, {ssl, true}}, _, _) ->
111 66 {keep_state_and_data, nei({upgrade, #{}})};
112
113 handle_event(internal, {response, #{label := upgrade, reply := ok}}, _, _) ->
114 66 {keep_state_and_data, nei({startup, #{}})};
115
116 handle_event(internal,
117 {startup = EventName, KV},
118 _,
119 #{config := #{user := User,
120 database := Database,
121 replication := Replication}}) ->
122 66 {keep_state_and_data,
123 [nei({send,
124 size_inclusive(
125 [marshal(int32, version()),
126 maps:fold(
127 fun
128 (K, V, A) ->
129 198 [marshal(string, K), marshal(string, V) | A]
130 end,
131 [],
132 maps:merge(
133 #{<<"user">> => User,
134 <<"database">> => Database,
135 <<"replication">> => Replication},
136 KV)),
137 marshal(byte, <<0>>)])}),
138 nei({telemetry,
139 EventName,
140 #{count => 1},
141 #{user => User,
142 database => Database}})]};
143
144 handle_event(internal,
145 {recv = EventName,
146 {authentication = Tag, authenticated = Type}}, State, Data)
147 when State == unready; State == starting ->
148
:-(
{next_state,
149 authenticated,
150 Data,
151 nei({telemetry, EventName, #{count => 1}, #{tag => Tag, type => Type}})};
152
153 handle_event(internal,
154 {recv, {ready_for_query, _} = TM},
155 authenticated,
156 #{config := #{replication := Replication}} = Data) ->
157 66 {next_state, TM, Data, nei({replication, Replication})};
158
159 handle_event(internal, {replication = EventName, Type}, _, _) ->
160 66 {keep_state_and_data,
161 [{change_callback_module, bootstrap_complete_callback_module(Type)},
162 nei({telemetry, EventName, #{count => 1}, #{type => Type}}),
163 nei(bootstrap_complete)]};
164
165 handle_event(internal,
166 {recv = EventName,
167 {authentication = Tag,
168 {sasl = Type, _} = SASL}},
169 _,
170 _) ->
171 66 {keep_state_and_data,
172 [{push_callback_module, pgmp_mm_auth_sasl},
173 nei({telemetry, EventName, #{count => 1}, #{tag => Tag, type => Type}}),
174 nei(SASL)]};
175
176 handle_event(internal,
177 {recv = EventName,
178 {authentication = Tag,
179 {md5_password = Type, _} = MD5}},
180 _,
181 _) ->
182
:-(
{keep_state_and_data,
183 [{push_callback_module, pgmp_mm_auth_md5},
184 nei({telemetry, EventName, #{count => 1}, #{tag => Tag, type => Type}}),
185 nei(MD5)]};
186
187 handle_event(internal,
188 {recv = EventName, {backend_key_data = Tag, [PID, Key]}},
189 _,
190 Data) ->
191 66 {keep_state,
192 Data#{backend => #{pid => PID, key => Key}},
193 nei({telemetry, EventName, #{count => 1}, #{tag => Tag}})};
194
195 handle_event(EventType, EventContent, State, Data) ->
196 4093 pgmp_mm_common:handle_event(EventType,
197 EventContent,
198 State,
199 Data).
200
201
202 version() ->
203 66 <<Version:32>> = <<(pgmp_config:protocol(major)):16,
204 (pgmp_config:protocol(minor)):16>>,
205 66 Version.
206
207
208 bootstrap_complete_callback_module(<<"false">>) ->
209 61 pgmp_mm_squery;
210
211 bootstrap_complete_callback_module(<<"database">>) ->
212 5 pgmp_mm_rep_log;
213
214 bootstrap_complete_callback_module(Physical) when Physical == <<"true">>;
215 Physical == <<"on">>;
216 Physical == <<"yes">>;
217 Physical == <<"1">> ->
218
:-(
pgmp_mm_rep_phy.
Line Hits Source