Dets Эрланга не создает файл с open_file

Это моя первая попытка написать что-нибудь на Эрланге, так что, возможно, вопрос глупый.

Я пишу довольно простой HTTP-сервер, используя ковбой

db_name() -> "DB_test".

timestamp() ->
    calendar:datetime_to_gregorian_seconds(calendar:universal_time()).

sha(Str) ->
    <<X:256/big-unsigned-integer>> = crypto:hash(sha256, Str),
    lists:flatten(io_lib:format("~64.16.0b", [X])).

handle_post(Req0, State) -> 
    Link = binary_to_list(cowboy_req:header(<<"link">>, Req0)),
    dets:open_file(db_name(), []),
    dets:insert(db_name(), {hashed_url(Link), Link, timestamp()}),

    Req = cowboy_req:reply(200,
        #{<<"content-type">> => <<"text/plain">>},
        sha(Link),
        Req0),
    {ok, Req, State}.

Идея состоит в том, что HTTP-запрос POST содержит заголовок "link" с некоторой ссылкой. После получения такого запроса мой сервер должен сохранить свой хэш в таблице dets вместе со ссылкой и его отметкой времени. Проблема в том, что файл "DB_test" не создан. Зачем?

1 ответ

Исходя из вашего примера кода, трудно сказать точно, почему, так как вы игнорируете возвращаемые значения как из dets:open_file/2, так и из dets:insert/2. Оба они возвращают разные значения для случаев успеха и неудачи; но не бросайте исключения. Для получения более подробной информации смотрите официальную документацию: http://erlang.org/doc/man/dets.html

Самым простым решением этого является сбой процесса обработки ковбойских соединений в неуспешных случаях. Вы можете сделать это, выполнив что-то вроде следующего:

 {ok, Ref} = dets:open_file(db_name(), []),
 ok = dets:insert(Ref, {hashed_url(Link), Link, timestamp()}),

Это приведет к аварийному завершению с ошибкой несоответствия в тех случаях, когда возвращаемое значение не может быть сопоставлено с шаблоном в левой части оператора, что впоследствии заставляет ковбоя вернуть HTTP 500 клиенту. Затем вы увидите подробную информацию о том, что было зарегистрировано в журнале

Вторым решением будет явная обработка случаев сбоя, для этого вы можете использовать ключевое слово case. Примером будет что-то вроде:

case dets:open_file(db_name(), []) of
   {ok, Ref} ->
       do_success_things();
   {error, Reason}=E ->
       io:format("Unable to open database file: ~p~n", [E]),
       do_failure_things();
end

Для дальнейшего чтения я настоятельно рекомендую использовать синтаксис в главах " Функции" и " Ошибки" и "Исключения" в разделе "Изучите Эрланг": http://learnyousomeerlang.com/

Другие вопросы по тегам