diff --git a/Common/Redis/RedisKeyList.cs b/Common/Redis/RedisKeyList.cs index 0ae00e3..bb65f27 100644 --- a/Common/Redis/RedisKeyList.cs +++ b/Common/Redis/RedisKeyList.cs @@ -56,5 +56,13 @@ { return $"white_list{sn}"; } + /// + /// 所有用户位置 + /// + /// + public static string UserLocation(long userId) + { + return $"user_locationbyid_{userId}"; + } } } diff --git a/Common/Redis/RedisService.cs b/Common/Redis/RedisService.cs index dc7c8f4..63fdbb7 100644 --- a/Common/Redis/RedisService.cs +++ b/Common/Redis/RedisService.cs @@ -10,6 +10,7 @@ namespace LY.App.Common.Redis public class RedisService { private readonly IDatabase _db; + private readonly IServer _redis; /// /// 构造函数 @@ -38,44 +39,82 @@ namespace LY.App.Common.Redis string jsonData = await _db.StringGetAsync(key); return jsonData is not null ? JsonSerializer.Deserialize(jsonData) : default; } - /// - /// 删除 Key + /// 模糊 查询所有 Key /// - public async Task DeleteAsync(string key) + /// + /// + public async Task> GetAllKeysAsync(string pattern) { - return await _db.KeyDeleteAsync(key); - } - - /// - /// 检查 Key 是否存在 - /// - public async Task ExistsAsync(string key) - { - return await _db.KeyExistsAsync(key); - } - /// - /// 获取数据,如果不存在则从数据源获取并存入 Redis - /// - /// 数据类型 - /// Redis Key - /// 数据源方法 - /// 可选的过期时间 - /// 获取到的值 - public async Task GetOrSetAsync(string key, Func> factory, TimeSpan? expiry = null) - { - var value = await GetAsync(key); - if (value is not null) + var redis = _db.Multiplexer; + var keys = new List(); + foreach (var endPoint in redis.GetEndPoints()) { + var server = redis.GetServer(endPoint); + + if (!server.IsConnected) + continue; + + // 使用 SCAN 获取匹配的 key,避免 KEYS 阻塞 + var scanKeys = server.Keys(pattern: pattern, pageSize: 1000); + keys.AddRange(scanKeys); + } + return keys; + //var result = new Dictionary(); + + //if (keys.Count > 0) + //{ + // // 一次批量获取 value + // var values = await _db.StringGetAsync(keys.ToArray()); + + // for (int i = 0; i < keys.Count; i++) + // { + // if (values[i].HasValue) + // { + // result[keys[i]] = values[i]; + // } + // } + //} + + //return result; + } + /// + /// 删除 Key + /// + public async Task DeleteAsync(string key) + { + return await _db.KeyDeleteAsync(key); + } + + /// + /// 检查 Key 是否存在 + /// + public async Task ExistsAsync(string key) + { + return await _db.KeyExistsAsync(key); + } + /// + /// 获取数据,如果不存在则从数据源获取并存入 Redis + /// + /// 数据类型 + /// Redis Key + /// 数据源方法 + /// 可选的过期时间 + /// 获取到的值 + public async Task GetOrSetAsync(string key, Func> factory, TimeSpan? expiry = null) + { + var value = await GetAsync(key); + if (value is not null) + { + return value; + } + + value = await factory(); + if (value is not null) + { + await SetAsync(key, value, expiry); + } return value; } - - value = await factory(); - if (value is not null) - { - await SetAsync(key, value, expiry); - } - return value; } } -} diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index c63b487..0461a23 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -4,6 +4,8 @@ using LY.App.Model; using LY.App.Service; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using StackExchange.Redis; +using System.Reactive.Joins; namespace LY.App.Controllers { @@ -51,14 +53,44 @@ namespace LY.App.Controllers TimeSpan.FromDays(1)); var weather = await _redisService.GetOrSetAsync(RedisKeyList.Index_Weather, async () => await _weatherService.GetWeather(), - TimeSpan.FromHours(3)); + TimeSpan.FromHours(3)); + + var data = await GetUserLocation(); result.data = new { positions, alarmCount, - weather + weather, + userLocation = data }; return Ok(result); } + + private async Task> GetUserLocation() + { + var keys = await _redisService.GetAllKeysAsync("user_locationbyid_*"); + List result = new List(); + if (keys.Count > 0) + { + foreach (var item in keys) + { + result.Add(await _redisService.GetAsync(item)); + } + } + return result; + } + + /// + /// 同步移动端位置信息 + /// + /// + /// + [HttpPost("syncLocation")] + public async Task SyncLocation(SyncLocation input) + { + string key = RedisKeyList.UserLocation(input.userId); + await _redisService.SetAsync(key, new SyncLocation() { userId = input.userId, lat = input.lat, lon = input.lon }, TimeSpan.FromMinutes(1)); + return Ok(new ApiResult()); + } } } diff --git a/Model/SyncLocation.cs b/Model/SyncLocation.cs new file mode 100644 index 0000000..5fe354c --- /dev/null +++ b/Model/SyncLocation.cs @@ -0,0 +1,20 @@ +namespace LY.App.Model +{ + /// + /// 移动端同步坐标信息 + /// + public class SyncLocation + { + public long userId { get; set; } + public double lon { get; set; } + public double lat { get; set; } + } + /// + /// web 端同步坐标信息 + /// + public class Location + { + public double lon { get; set; } + public double lat { get; set; } + } +}