Skip to content

Commit

Permalink
Include queue for the requests
Browse files Browse the repository at this point in the history
To ensure we are not sending too many requests at once
  • Loading branch information
codeserk committed May 30, 2020
1 parent 0d3bf9c commit 8a82a45
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 39 deletions.
143 changes: 110 additions & 33 deletions Editor/WakaTime/ClientManager.cs
@@ -1,14 +1,55 @@
using System.Diagnostics;
using System.IO;
using UnityEngine;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;

namespace WakaTime
{
/// <summary>
/// Client request.
/// Contains the information needed to make 1 wakatime heartbeat.
/// </summary>
public readonly struct ClientRequest
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="apiKey"></param>
/// <param name="file"></param>
public ClientRequest(string apiKey, string file)
{
this.apiKey = apiKey;
this.file = file;
}

/// <summary>
/// WakaTime API Key
/// </summary>
public readonly string apiKey;

/// <summary>
/// File to sned to wakatime.
/// </summary>
public readonly string file;
}

/// <summary>
/// Handles operations with wakatime client.
/// </summary>
public class ClientManager
{
/// <summary>
/// Requests stacks
/// </summary>
protected static readonly Queue<ClientRequest> requests = new Queue<ClientRequest>();

/// <summary>
/// Number of active requests.
/// </summary>
protected static int activeRequests = 0;

/// <summary>
/// Gets the base directory where wakatime is installed.
/// </summary>
Expand Down Expand Up @@ -65,54 +106,90 @@ public static bool IsClientLatestVersion()
/// <param name="apiKey"></param>
/// <param name="file"></param>
/// <param name="write"></param>
public static void HeartBeat(string apiKey, string file, bool write = false)
public async static Task HeartBeat(string apiKey, string file, bool write = false)
{
if (!PythonManager.IsPythonInstalled()) return;
if (activeRequests < Main.MaxRequests)
{
activeRequests++;

string arguments = "--key " + apiKey +
" --file " + "\"" + file + "\"" +
" --plugin " + WakaTimeConstants.PLUGIN_NAME +
" --project " + "\"" + Main.GetProjectName() + "\"" +
" --verbose";
if (Main.IsDebug)
{
UnityEngine.Debug.Log("[wakatime] Making request: " + activeRequests + " / " + Main.MaxRequests + " (enqueued: " + requests.Count + ")");
}

if (Main.IsDebug)
{
UnityEngine.Debug.Log("[wakatime] Sending file: " + PythonManager.GetPythonPath() + " " + GetClientPath() +
" " + arguments);
}
var dataPath = Application.dataPath;
var projectName = Main.GetProjectName();
var clientPath = GetClientPath();
await Task.Run(() => MakeRequest(apiKey, file, projectName, dataPath, clientPath));

Process p = new Process
activeRequests--;
if (requests.Count > 0)
{
var request = requests.Dequeue();
await HeartBeat(request.apiKey, request.file);
}
}
else
{
StartInfo = {
FileName = PythonManager.GetPythonPath (),
Arguments = "\"" + GetClientPath () + "\" " + arguments,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = Application.dataPath,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
if (Main.IsDebug)
{
UnityEngine.Debug.Log("[wakatime] Request enqueued (" + requests.Count + ")");
}
};

p.Start();
requests.Enqueue(new ClientRequest(apiKey, file));
}
}

if (Main.IsDebug)
/// <summary>
/// Sends a heart-beat to wakatime.
/// Only works if the client is not installed.
/// </summary>
/// <param name="apiKey"></param>
/// <param name="projectName"></param>
/// <param name="file"></param>
/// <param name="dataPath"></param>
/// <param name="clientPath"></param>
protected static void MakeRequest(string apiKey, string file, string projectName, string dataPath, string clientPath)
{
try
{
var output = p.StandardOutput.ReadToEnd();
if (output.Length > 0)
string arguments = "--key " + apiKey +
" --file " + "\"" + file + "\"" +
" --plugin " + WakaTimeConstants.PLUGIN_NAME +
" --project " + "\"" + projectName + "\"" +
" --verbose";

if (Main.IsDebug)
{
UnityEngine.Debug.Log("[wakatime] Output: " + output);
UnityEngine.Debug.Log("[wakatime] Sending file: " + file);
}

var errors = p.StandardError.ReadToEnd();
if (errors.Length > 0)
Process p = new Process
{
UnityEngine.Debug.LogError("[wakatime] Error: " + errors);
StartInfo = {
FileName = PythonManager.GetPythonPath (),
Arguments = "\"" + clientPath + "\" " + arguments,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = dataPath,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
}
};

p.Start();
p.WaitForExit(5000);

UnityEngine.Debug.Log("[wakatime] Finished sending file " + file);
}
catch (Exception ex)
{
if (Main.IsDebug)
{
UnityEngine.Debug.LogError("[wakatime] Error found while sending heartbeat to wakatime for file " + file + ": " + ex);
}
}

p.Close();
}
}
}
42 changes: 38 additions & 4 deletions Editor/WakaTime/Main.cs
Expand Up @@ -29,6 +29,11 @@ public class Main
/// </summary>
public const string KEY_API_KEY = "wakatime_api_key";

/// <summary>
/// Key in editor preferences to get max requests.
/// </summary>
public const string KEY_MAX_REQUESTS = "wakatime_max_requests";

/// <summary>
/// Name of the current scene.
/// </summary>
Expand Down Expand Up @@ -113,6 +118,35 @@ public static bool IsDebug
}
}

/// <summary>
/// Maximun number of concurrent requests to wakatime.
/// 5 by default.
/// </summary>
static int? _maxRequests = null;

/// <summary>
/// Max requests wrapper.
/// Gets the value from the editor preferences if it's not set.
/// Saves the new value in the editor preferences.
/// </summary>
public static int MaxRequests
{
get
{
if (_maxRequests == null)
{
_maxRequests = EditorPrefs.GetInt(KEY_API_KEY, 5);
}

return (int)_maxRequests;
}
set
{
_maxRequests = value;
EditorPrefs.SetInt(KEY_MAX_REQUESTS, value);
}
}

/// <summary>
/// Last times when the files changed.
/// {file path} => {last updated at}
Expand Down Expand Up @@ -167,7 +201,7 @@ public static bool Check()
{
bool res = false;

// Checking pythong client is expensive, so only do if the API key is set.
// Checking python client is expensive, so only do if the API key is set.
if (CheckAPIKey())
{
res = CheckPython();
Expand Down Expand Up @@ -292,11 +326,11 @@ public static void OnAssetSaved(string path)
/// </summary>
/// <param name="path">File path</param>
/// <param name="write"></param>
static void RequestSendFile(string path, bool write = false)
static async void RequestSendFile(string path, bool write = false)
{
if (Check() && ShouldSendFile(path))
{
ClientManager.HeartBeat(GetApiKey(), path, write);
await ClientManager.HeartBeat(GetApiKey(), path, write);
}
}

Expand Down Expand Up @@ -344,7 +378,7 @@ static bool ShouldSendFile(string path)
Debug.Log("[wakatime] Should send " + path.Substring(path.LastIndexOf("/") + 1) + "? [" + (shouldSendFile ? "yes" : "no") + "]");
}

return shouldSendFile;
return true;
}
}
}
8 changes: 6 additions & 2 deletions Editor/WakaTime/PythonInstaller.cs
Expand Up @@ -5,6 +5,8 @@

using System.IO;

#pragma warning disable 612, 618

namespace WakaTime
{
/// <summary>
Expand Down Expand Up @@ -122,7 +124,7 @@ static void DownloadCompleted()

if (Main.IsDebug)
{
UnityEngine.Debug.Log("Python downloaded: " + www.size.ToString());
UnityEngine.Debug.Log("Python downloaded: " + www.bytesDownloaded.ToString());
}
string dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string localFile = dir + PythonManager.GetPythonFileName();
Expand Down Expand Up @@ -183,4 +185,6 @@ static void Install()
}
}
}
}
}

#pragma warning restore 612, 618
2 changes: 2 additions & 0 deletions Editor/WakaTime/Window.cs
Expand Up @@ -41,6 +41,8 @@ void OnGUI()
{
EditorGUILayout.HelpBox("API Key is required", MessageType.Error, false);
}
Main.MaxRequests = EditorGUILayout.IntField("Max Requests", Main.MaxRequests);
EditorGUILayout.HelpBox("Maximum number of simultaneous requests to wakatime. Be cautious when increasing this value, since that might cause CPU problems.", MessageType.Info, true);

EditorGUILayout.Separator();

Expand Down

0 comments on commit 8a82a45

Please sign in to comment.