如何在不淹没NIC的情况下统一监视数据库中的更改

时间:2019-01-31 00:44:01

标签: php mysql unity3d webrequest

我有一个包含sql数据库的Web服务器。此服务器/数据库有两个“用户”。一个是实际用户,他们将使用HTTP:Post通过UnityWebRequest提交更改。这将对数据库进行更改。

我还有另一个也在Unity中的系统,需要对它进行通知,或者无论何时对数据库中的特定表进行更改,都需要进行监视。我不知道如何在不不断对数据库进行选择调用的情况下监视表的更改。

我尝试过的

我有一个统一的功能,可以通过HTTP:Post调用网络服务器。网络服务器进入一个无限的while循环,对该数据库进行调用,例如

$variable = $_REQUEST['variable_to_monitor'];
$stmt = $pdo->prepare("SELECT variable_to_monitor FROM table_name;")
while(true){
    $stmt->execute();
    results = $stmt->fetchAll()[0];
    if ($variable != results['variable_to_monitor']){
        die(results['variable_to_monitor']);
    }
}

这将阻止Web服务器,并且正在对数据库进行过多调用。

我希望Unity能够对给定状态的Web服务器进行一次调用,Web服务器将把该状态与数据库进行比较,直到数据库发生更改,然后一旦db更改对与更新状态。我希望能够做到这一点,而不必每秒对数据库进行百万次SELECT调用。

统一代码


    void Update()
    {
        if(hasResponse)
        {
            hasResponse = false;
            StartCoroutine(SendRequest());
        }
    }

    IEnumerator SendRequest(WWWForm form = null, Action<string> callback = null)
    {
        if(null == form) form = new WWWForm();
        form.AddField("request", "monitor_variable");
        form.AddField("variable_to_monitor", this.variable_to_monitor);

        UnityWebRequest www = UnityWebRequest.Post(url, form);
        yield return www.SendWebRequest();

        if (www.isNetworkError)
        {
            Debug.Log("Network Error");
        }
        else if (www.isHttpError)
        {
            Debug.Log("Http Error");
        }
        else
        {
            if(null == callback)
            {
                Debug.Log(www.downloadHandler.text);
            }
            else
            {
                if (!www.downloadHandler.text.Contains("New Request Started"))
                {
                    hasResponse = true;
                    callback(www.downloadHandler.text);
                }
                else
                {
                    Debug.Log(www.downloadHandler.text);
                }
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

当然,你可以总是要在Unity等待UnityWebRequest来完成!你应该使用永诺如Coroutine

例如,您也可以做到添加时间偏移,这样您就不会立即提出新请求,而可能要等待几秒钟。

我个人也将为响应添加回调,从而使响应方式更加灵活和可重用。

public void MakeRepeatedRequests(string url, float timeOffset, Action<string> successCallback, Action<string> errorCallback)
{
    StartCoroutine(RepeatedRequestRoutine(url, timeOffset, successCallback, errorCallback);
}

private IEnumerator RepeatedRequestRoutine(string url, float timeOffset, Action<string> successCallback, Action<string> errorCallback)
{
    // No worries this still looks like a while loop (well it is ^^)
    // but the yield makes sure it doesn't block Unity's UI thread
    while(true)
    {
        // Configure your request
        var request = UnityWebRequest.Post(url);

        // Make the request and wait until the it has finished (has a response or timeout)
        // a yield kind of tells this routine to leave, let Unity render this frame
        // and continue from here in the next frame
        yield return request.SendWebRequest();

        if(request.isNetworkError || request.isHttpError) 
        {
            errorCallback?.Invoke(request.error);
        }
        else 
        {
            successCallback?.Invoke(request.downloadHandler.text);
        }

        // Now wait for the timeOffset
        yield return new WaitForSeconds(timeOffset);
    }
}

现在您可以将其命名为等待最后一个请求后2秒完成

// ...

    MakeRepeatedRequests ("http://example.com", 2.0f, OnSuccess, OnError);

// ...

private void OnSuccess(string success)
{
    Debug.LogFormat(this, "Nice it worked! Server said:/"{0}/"", success);

    // Do something e.g. using success
}

private void OnError(string error)
{
    Debug.LogFormat(this, "Oh no, request failed with \"{0}\"", error);
}

或也使用lambda表达式做同样的事情

MakeRepeatedRequests ("http://example.com", 2.0f, 

    success =>
    {
        Debug.LogFormat(this, "Nice it worked! Server said:/"{0}/"", success);

        // Do something e.g. using success
    }, 

    error =>
    {
        Debug.LogFormat(this, "Oh no, request failed with \"{0}\"", error);

        // Do something else
    });

即使你不想timeOffset这在开始下一个让你的服务器只需要做出一个数据库查询,然后返回一个成功或错误。之前至少等待每个请求完成< / p>

在你的情况我会成功(200)反正响应(因为只应发送错误,如果服务器确实出现错误),但无论是发送一个空string或一些预定义的一个,你可以检查统一(像例如,"!NO_CHANGE!")。

因此在服务器端没有循环之类的东西

results = "SELECT * FROM table_name;"
if ($_REQUEST['variable_name'] != results['variable_name']){
    echo results['variable_name'];
} else {
    echo "!NO_CHANGE!";
}

比你以后可以在统一检查

if(string.Equals(success, "!NO_CHANGE!")) return;