Compare commits
No commits in common. "master" and "v1.0.0" have entirely different histories.
@ -1,65 +0,0 @@
|
|||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup .NET
|
|
||||||
uses: actions/setup-dotnet@v3
|
|
||||||
with:
|
|
||||||
dotnet-version: '9.0.x'
|
|
||||||
|
|
||||||
- name: Restore dependencies
|
|
||||||
run: dotnet restore Firefly.sln
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
chmod +x build-all.sh
|
|
||||||
./build-all.sh
|
|
||||||
|
|
||||||
- name: Create Release
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
name: Firefly v1.0.0 - Initial Release
|
|
||||||
body: |
|
|
||||||
# Firefly v1.0.0 - Initial Release
|
|
||||||
|
|
||||||
We're excited to announce the initial release of Firefly! This version includes the core functionality of our application.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
- Native library support for enhanced performance
|
|
||||||
- Self-contained executable builds
|
|
||||||
- Cross-platform compatibility (Linux, macOS)
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
Choose the appropriate build for your platform from the assets below.
|
|
||||||
|
|
||||||
## System Requirements
|
|
||||||
- .NET 9.0 Runtime (for non-self-contained builds)
|
|
||||||
- Linux x64, macOS x64, or Windows x64
|
|
||||||
|
|
||||||
## Known Issues
|
|
||||||
- None reported
|
|
||||||
|
|
||||||
## What's Next
|
|
||||||
- Additional platform support
|
|
||||||
- Performance optimizations
|
|
||||||
- Enhanced documentation
|
|
||||||
|
|
||||||
## Feedback
|
|
||||||
We welcome your feedback and bug reports. Please use the issue tracker to report any problems.
|
|
||||||
files: |
|
|
||||||
artifacts/exe/*
|
|
||||||
artifacts/native/*
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -227,13 +227,6 @@
|
|||||||
<param name="args">Command arguments containing the key</param>
|
<param name="args">Command arguments containing the key</param>
|
||||||
<returns>The popped value or nil if the list is empty</returns>
|
<returns>The popped value or nil if the list is empty</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:Firefly.Firefly.HandleLLengthCommand(System.String)">
|
|
||||||
<summary>
|
|
||||||
Handles the LLEN command which returns the length of a list.
|
|
||||||
</summary>
|
|
||||||
<param name="args">Command arguments containing the key</param>
|
|
||||||
<returns>The length of the list or 0 if the key does not exist</returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:Firefly.Firefly.HandleLRangeCommand(System.String)">
|
<member name="M:Firefly.Firefly.HandleLRangeCommand(System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
Handles the LRANGE command which returns a range of elements from a list.
|
Handles the LRANGE command which returns a range of elements from a list.
|
||||||
@ -320,11 +313,6 @@
|
|||||||
<param name="key">The key to execute the action on</param>
|
<param name="key">The key to execute the action on</param>
|
||||||
<param name="action">The action to execute</param>
|
<param name="action">The action to execute</param>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:Firefly.Firefly.DisplayFireflyArt">
|
|
||||||
<summary>
|
|
||||||
Displays Firefly ASCII art in the console
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:Firefly.Firefly.HandleAuthCommand(System.String,System.String)">
|
<member name="M:Firefly.Firefly.HandleAuthCommand(System.String,System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
Handles the AUTH command which authenticates a client.
|
Handles the AUTH command which authenticates a client.
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -227,13 +227,6 @@
|
|||||||
<param name="args">Command arguments containing the key</param>
|
<param name="args">Command arguments containing the key</param>
|
||||||
<returns>The popped value or nil if the list is empty</returns>
|
<returns>The popped value or nil if the list is empty</returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:Firefly.Firefly.HandleLLengthCommand(System.String)">
|
|
||||||
<summary>
|
|
||||||
Handles the LLEN command which returns the length of a list.
|
|
||||||
</summary>
|
|
||||||
<param name="args">Command arguments containing the key</param>
|
|
||||||
<returns>The length of the list or 0 if the key does not exist</returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:Firefly.Firefly.HandleLRangeCommand(System.String)">
|
<member name="M:Firefly.Firefly.HandleLRangeCommand(System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
Handles the LRANGE command which returns a range of elements from a list.
|
Handles the LRANGE command which returns a range of elements from a list.
|
||||||
@ -320,11 +313,6 @@
|
|||||||
<param name="key">The key to execute the action on</param>
|
<param name="key">The key to execute the action on</param>
|
||||||
<param name="action">The action to execute</param>
|
<param name="action">The action to execute</param>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:Firefly.Firefly.DisplayFireflyArt">
|
|
||||||
<summary>
|
|
||||||
Displays Firefly ASCII art in the console
|
|
||||||
</summary>
|
|
||||||
</member>
|
|
||||||
<member name="M:Firefly.Firefly.HandleAuthCommand(System.String,System.String)">
|
<member name="M:Firefly.Firefly.HandleAuthCommand(System.String,System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
Handles the AUTH command which authenticates a client.
|
Handles the AUTH command which authenticates a client.
|
||||||
|
@ -8,13 +8,6 @@ namespace Firefly
|
|||||||
public partial class Firefly
|
public partial class Firefly
|
||||||
{
|
{
|
||||||
#region Backup System
|
#region Backup System
|
||||||
// Track if data has been modified since last backup
|
|
||||||
private static volatile bool dataModified = false;
|
|
||||||
// Debounce period in milliseconds for data modification backups
|
|
||||||
private static readonly int dataModificationBackupDelayMs = 5000;
|
|
||||||
// Timer for debouncing data modification backups
|
|
||||||
private static System.Timers.Timer? modificationBackupTimer;
|
|
||||||
|
|
||||||
static void InitializeBackupSystem()
|
static void InitializeBackupSystem()
|
||||||
{
|
{
|
||||||
// Create backup directory if it doesn't exist
|
// Create backup directory if it doesn't exist
|
||||||
@ -40,21 +33,7 @@ namespace Firefly
|
|||||||
backupTimer.AutoReset = true;
|
backupTimer.AutoReset = true;
|
||||||
backupTimer.Start();
|
backupTimer.Start();
|
||||||
|
|
||||||
// Set up data modification backup timer
|
|
||||||
modificationBackupTimer = new System.Timers.Timer(dataModificationBackupDelayMs);
|
|
||||||
modificationBackupTimer.Elapsed += (sender, e) =>
|
|
||||||
{
|
|
||||||
if (dataModified)
|
|
||||||
{
|
|
||||||
BackupData();
|
|
||||||
dataModified = false;
|
|
||||||
}
|
|
||||||
modificationBackupTimer.Stop(); // Stop timer after backup
|
|
||||||
};
|
|
||||||
modificationBackupTimer.AutoReset = false;
|
|
||||||
|
|
||||||
Console.WriteLine($"Automatic backup system initialized (every {autoBackupIntervalMinutes} minutes)");
|
Console.WriteLine($"Automatic backup system initialized (every {autoBackupIntervalMinutes} minutes)");
|
||||||
Console.WriteLine($"Data modification backup system initialized (after {dataModificationBackupDelayMs/1000} seconds of inactivity)");
|
|
||||||
Console.WriteLine($"Keeping up to {maxBackupFiles} backup files");
|
Console.WriteLine($"Keeping up to {maxBackupFiles} backup files");
|
||||||
|
|
||||||
// Register backup on exit
|
// Register backup on exit
|
||||||
@ -68,22 +47,6 @@ namespace Firefly
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call this method whenever data is modified
|
|
||||||
internal static void MarkDataAsModified()
|
|
||||||
{
|
|
||||||
if (!backupsEnabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dataModified = true;
|
|
||||||
|
|
||||||
// Reset and start the timer to debounce multiple rapid changes
|
|
||||||
if (modificationBackupTimer != null)
|
|
||||||
{
|
|
||||||
modificationBackupTimer.Stop();
|
|
||||||
modificationBackupTimer.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void LoadDataFromBackup()
|
static void LoadDataFromBackup()
|
||||||
{
|
{
|
||||||
if (!backupsEnabled)
|
if (!backupsEnabled)
|
||||||
|
@ -188,10 +188,7 @@ namespace Firefly
|
|||||||
|
|
||||||
case "LINDEX":
|
case "LINDEX":
|
||||||
return HandleLIndexCommand(parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : "");
|
return HandleLIndexCommand(parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : "");
|
||||||
|
|
||||||
case "LLEN":
|
|
||||||
return HandleLLengthCommand(parts.Length > 1 ? parts[1] : "");
|
|
||||||
|
|
||||||
case "LRANGE":
|
case "LRANGE":
|
||||||
return HandleLRangeCommand(parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : "");
|
return HandleLRangeCommand(parts.Length > 1 ? string.Join(" ", parts.Skip(1)) : "");
|
||||||
|
|
||||||
|
@ -27,11 +27,10 @@ namespace Firefly
|
|||||||
{
|
{
|
||||||
var hash = GetOrCreateHash(key);
|
var hash = GetOrCreateHash(key);
|
||||||
bool isNewField = hash.TryAdd(field, value);
|
bool isNewField = hash.TryAdd(field, value);
|
||||||
|
|
||||||
if (!isNewField)
|
if (!isNewField)
|
||||||
|
{
|
||||||
hash[field] = value;
|
hash[field] = value;
|
||||||
|
}
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
return Encoding.UTF8.GetBytes($":{(isNewField ? 1 : 0)}\r\n");
|
return Encoding.UTF8.GetBytes($":{(isNewField ? 1 : 0)}\r\n");
|
||||||
}
|
}
|
||||||
@ -92,11 +91,10 @@ namespace Firefly
|
|||||||
{
|
{
|
||||||
bool removed = hash.TryRemove(field, out _);
|
bool removed = hash.TryRemove(field, out _);
|
||||||
|
|
||||||
if (removed)
|
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
if (hash.IsEmpty)
|
if (hash.IsEmpty)
|
||||||
|
{
|
||||||
HashStoreRemove(key);
|
HashStoreRemove(key);
|
||||||
|
}
|
||||||
|
|
||||||
return Encoding.UTF8.GetBytes($":{(removed ? 1 : 0)}\r\n");
|
return Encoding.UTF8.GetBytes($":{(removed ? 1 : 0)}\r\n");
|
||||||
}
|
}
|
||||||
@ -199,8 +197,6 @@ namespace Firefly
|
|||||||
return Encoding.UTF8.GetBytes($"-ERR internal error: {ex.Message}\r\n");
|
return Encoding.UTF8.GetBytes($"-ERR internal error: {ex.Message}\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
return Encoding.UTF8.GetBytes("+OK\r\n");
|
return Encoding.UTF8.GetBytes("+OK\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,12 +220,7 @@ namespace Firefly
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var hash = hashStoreShards[shardIndex].GetOrAdd(key, _ => new ConcurrentDictionary<string, string>());
|
return hashStoreShards[shardIndex].GetOrAdd(key, _ => new ConcurrentDictionary<string, string>());
|
||||||
|
|
||||||
if (hash.IsEmpty)
|
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -263,12 +254,7 @@ namespace Firefly
|
|||||||
private static bool HashStoreRemove(string key)
|
private static bool HashStoreRemove(string key)
|
||||||
{
|
{
|
||||||
int shardIndex = GetShardIndex(key);
|
int shardIndex = GetShardIndex(key);
|
||||||
bool result = hashStoreShards[shardIndex].TryRemove(key, out _);
|
return hashStoreShards[shardIndex].TryRemove(key, out _);
|
||||||
|
|
||||||
if (result)
|
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -152,26 +152,6 @@ namespace Firefly
|
|||||||
: Encoding.UTF8.GetBytes("$-1\r\n");
|
: Encoding.UTF8.GetBytes("$-1\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles the LLEN command which returns the length of a list.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">Command arguments containing the key</param>
|
|
||||||
/// <returns>The length of the list or 0 if the key does not exist</returns>
|
|
||||||
static byte[] HandleLLengthCommand(string args)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(args))
|
|
||||||
{
|
|
||||||
return Encoding.UTF8.GetBytes("-ERR wrong number of arguments for 'llen' command\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
string key = args.Trim();
|
|
||||||
|
|
||||||
// Change to use the generic method correctly by returning the length
|
|
||||||
int length = ListStoreWithReadLock(key, list => list.Count);
|
|
||||||
|
|
||||||
return Encoding.UTF8.GetBytes($":{length}\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles the LRANGE command which returns a range of elements from a list.
|
/// Handles the LRANGE command which returns a range of elements from a list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -548,13 +528,6 @@ namespace Firefly
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Key '{key}' already exists with a different type");
|
throw new InvalidOperationException($"Key '{key}' already exists with a different type");
|
||||||
}
|
}
|
||||||
|
|
||||||
var newList = new List<string>();
|
|
||||||
if (listStoreShards[shardIndex].TryAdd(key, newList))
|
|
||||||
{
|
|
||||||
MarkDataAsModified();
|
|
||||||
return newList;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return listStoreShards[shardIndex].GetOrAdd(key, _ => []);
|
return listStoreShards[shardIndex].GetOrAdd(key, _ => []);
|
||||||
@ -594,12 +567,7 @@ namespace Firefly
|
|||||||
listStoreLocks[shardIndex].EnterWriteLock();
|
listStoreLocks[shardIndex].EnterWriteLock();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool result = listStoreShards[shardIndex].TryRemove(key, out _);
|
return listStoreShards[shardIndex].TryRemove(key, out _);
|
||||||
|
|
||||||
if (result)
|
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -620,8 +588,6 @@ namespace Firefly
|
|||||||
{
|
{
|
||||||
var list = GetOrCreateList(key);
|
var list = GetOrCreateList(key);
|
||||||
action(list);
|
action(list);
|
||||||
|
|
||||||
MarkDataAsModified();
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -9,9 +9,6 @@ namespace Firefly
|
|||||||
#region Server Management
|
#region Server Management
|
||||||
static async Task StartServerAsync()
|
static async Task StartServerAsync()
|
||||||
{
|
{
|
||||||
// Display Firefly ASCII art
|
|
||||||
DisplayFireflyArt();
|
|
||||||
|
|
||||||
// Set up server on specified port
|
// Set up server on specified port
|
||||||
var listener = new TcpListener(IPAddress.Parse(bindAddress), serverPort);
|
var listener = new TcpListener(IPAddress.Parse(bindAddress), serverPort);
|
||||||
listener.Start();
|
listener.Start();
|
||||||
@ -308,38 +305,6 @@ namespace Firefly
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Displays Firefly ASCII art in the console
|
|
||||||
/// </summary>
|
|
||||||
static void DisplayFireflyArt()
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
||||||
Console.WriteLine(
|
|
||||||
" ,,_\n" +
|
|
||||||
" zd$$??=\n" +
|
|
||||||
" z$$P? F:`c, _\n" +
|
|
||||||
" d$$, `c'cc$$i ,cd$?R\n" +
|
|
||||||
" $$$$ cud$,?$$$i ,=P'2?z '\n" +
|
|
||||||
" $` ` ?$$$,?$$$. ,-''`>, bzP\n" +
|
|
||||||
" 'cLdb,?$$,?$$$ ,h' 'I$'J$P\n" +
|
|
||||||
" ... `?$$$,`$$,`$$h $$PxrF'd$'\n" +
|
|
||||||
" d$PP``?-,`?$$,?$h`$$,,$$'$F44'\n" +
|
|
||||||
" ?,,_`=4c,?=,`?hu?$`?L4$'? '\n" +
|
|
||||||
" ```?==``=-`` ```-`'_,,,,\n" +
|
|
||||||
" .ccu?m?e?JC,-,\"=?\n" +
|
|
||||||
" ```=='?'\n");
|
|
||||||
|
|
||||||
Console.WriteLine(@"
|
|
||||||
███████╗██╗██████╗ ███████╗███████╗██╗ ██╗ ██╗
|
|
||||||
██╔════╝██║██╔══██╗██╔════╝██╔════╝██║ ╚██╗ ██╔╝
|
|
||||||
█████╗ ██║██████╔╝█████╗ █████╗ ██║ ╚████╔╝
|
|
||||||
██╔══╝ ██║██╔══██╗██╔══╝ ██╔══╝ ██║ ╚██╔╝
|
|
||||||
██║ ██║██║ ██║███████╗██║ ███████╗██║
|
|
||||||
╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚══════╝╚═╝
|
|
||||||
");
|
|
||||||
Console.ResetColor();
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -88,9 +88,6 @@ namespace Firefly
|
|||||||
|
|
||||||
int shardIndex = GetShardIndex(key);
|
int shardIndex = GetShardIndex(key);
|
||||||
stringStoreShards[shardIndex][key] = value;
|
stringStoreShards[shardIndex][key] = value;
|
||||||
|
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,12 +111,7 @@ namespace Firefly
|
|||||||
private static bool StringStoreRemove(string key)
|
private static bool StringStoreRemove(string key)
|
||||||
{
|
{
|
||||||
int shardIndex = GetShardIndex(key);
|
int shardIndex = GetShardIndex(key);
|
||||||
bool result = stringStoreShards[shardIndex].TryRemove(key, out _);
|
return stringStoreShards[shardIndex].TryRemove(key, out _);
|
||||||
|
|
||||||
if (result)
|
|
||||||
MarkDataAsModified();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#endregion
|
#endregion
|
||||||
|
Loading…
x
Reference in New Issue
Block a user