Не удается подключиться к базе данных MySQL/MariaDB из вибрированного приложения

Все отлично работает, если я использую пользовательский основной (void main() вместо shared static this()).

По умолчанию основной я получаю ошибку "Access Violation". Похоже, MySQL не позволяет подключиться к нему из localhost, но в my.ini я добавил строку:

bind-address = 127.0.0.1

код, если это поможет:

import std.stdio;
import std.path;
import std.file;
import std.string;

import dini;
import vibe.d;
import colorize;
import ddbc.all;

shared static this()
{
    auto settings = new HTTPServerSettings;
    settings.port = 8080;
    settings.bindAddresses = ["::1", "127.0.0.1"];
    listenHTTP(settings, &hello);

    auto parseconfig = new ParseConfig();
    auto db = new DBConnect(parseconfig);
}

void hello(HTTPServerRequest req, HTTPServerResponse res)
{
    res.writeBody("Hello, World!");
}


class ParseConfig
{
    string dbname;
    string dbuser;
    string dbpass;
    string dbhost;
    string dbport;

this()
    {
        try
        {
            //getcwd do not return correct path if run from task shoulder
            string confpath = buildPath((thisExePath[0..((thisExePath.lastIndexOf("\\"))+1)]), "config.ini");
            //writefln(thisExePath[0..((thisExePath.lastIndexOf("\\"))+1)]); // get path without extention +1 is for getting last slash

            //string confpath = buildPath(thisExePath, "config.ini");
            if (!exists(confpath)) 
                {
                    writeln("ERROR: config.ini do not exists");
                }
            auto config = Ini.Parse(confpath);
            try
            {
                this.dbname = config.getKey("dbname");
                this.dbuser = config.getKey("dbuser");
                this.dbpass = config.getKey("dbpass");
                this.dbhost = config.getKey("dbhost");
                this.dbport = config.getKey("dbport");

            }
            catch (Exception msg)
            {
                cwritefln("ERROR: Can't parse config: %s".color(fg.red), msg.msg);
            }       
        }
        catch(Exception msg)
        {
            cwriteln(msg.msg.color(fg.red));
            core.thread.Thread.sleep( dur!("msecs")(1000));
        }   
    }


}


class DBConnect
{
    Statement stmt;
    ParseConfig parseconfig;

    this(ParseConfig parseconfig)
    {
        try
            {
                this.parseconfig = parseconfig;
                MySQLDriver driver = new MySQLDriver();
                string url = MySQLDriver.generateUrl(parseconfig.dbhost, to!short(parseconfig.dbport), parseconfig.dbname);
                string[string] params = MySQLDriver.setUserAndPassword(parseconfig.dbuser, parseconfig.dbpass);

                DataSource ds = new ConnectionPoolDataSourceImpl(driver, url, params);

                auto conn = ds.getConnection();
                scope(exit) conn.close();

                stmt = conn.createStatement();
                writefln("\n[Database connection OK]");
            }
        catch (Exception ex)
        {
            writefln(ex.msg);
            writeln("Could not connect to DB. Please check settings");
        }

    }   
}

Также я запускаю следующую команду:

GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION; FLUSH PRIVILEGES;

также я пробовал разные bind-address лайк: 0.0.0.0 а также localhost но без результата. После каждого нового связывания я перезагружал службу MySQL.

Я использую этот драйвер http://code.dlang.org/packages/ddbc

В чем дело?

2 ответа

Решение

Чтобы продолжить мой комментарий ( Не удается подключиться к базе данных MySQL/MariaDB из вибрированного приложения).

Я только что проверил, и это определенно цикл событий;)

Вместо:

auto parseconfig = new ParseConfig();
auto db = new DBConnect(parseconfig);

Просто делать:

runTask({
    auto parseconfig = new ParseConfig();
    auto db = new DBConnect(parseconfig);
});

Работал для меня (DMD 2.067.0 / Vibe 0.7.23 / ddbc 0.2.24 / colorize & dini master).

Чтобы ответить на ваш комментарий ( Не удается подключиться к базе данных MySQL/MariaDB из вибрированного приложения): цикл обработки событий начинается внутри главной функции. Что происходит, когда вы запускаете приложение D? Точка входа - это C-main внутри среды выполнения, которая инициализирует ее (среду выполнения), включая конструктор модуля, запускает unittest (если вы скомпилировали с помощью -unittest), а затем вызывает вашу main (имя которой _Dmain) - полезно знать, хотите ли вы установить точку останова с помощью GDB). Когда вызывается main файла Vibe.d, он анализирует аргумент командной строки, необязательный файл конфигурации и, наконец, запускает цикл обработки событий. Любой код, который нужно запустить после запуска цикла событий, должен использовать runTask и тому подобное, или createTimer, Они не должны вызывать код напрямую из статического конструктора (это на самом деле одна из самых распространенных ошибок при запуске с Vibe.d).

Я столкнулся с проблемой, которая могла быть связана при разработке mysql-lited, альтернативного драйвера MySQL/MariaDB.

Я думаю, что эта проблема связана с ошибкой порядка инициализации модуля в phobos/SHA1, которая, как мне кажется, все еще открыта в 2.067.1. Предложенный обходной путь - вместо этого использовать VibeCustomMain и определить свой собственный метод main(). Вы можете просто скопировать defaul main() из appmain.d и использовать его.

В качестве альтернативы вы можете попробовать mysql-lited и посмотреть, будет ли это работать лучше для вас.

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