import 'dart:async'; import 'dart:convert'; import 'package:angel_framework/angel_framework.dart'; import 'package:resp_client/resp_client.dart'; import 'package:resp_client/resp_commands.dart'; /// An Angel service that reads and writes JSON within a Redis store. class RedisService extends Service> { final RespCommandsTier2 respCommands; /// An optional string prefixed to keys before they are inserted into Redis. /// /// Consider using this if you are using several different Redis collections /// within a single application. final String? prefix; RedisService(this.respCommands, {this.prefix}); String? _applyPrefix(String? id) => prefix == null ? id : '$prefix:$id'; @override Future>> index( [Map? params]) async { var result = //await respCommands.client.writeArrayOfBulk(['KEYS', _applyPrefix('*')]); await respCommands.tier1.tier0.execute(['KEYS', _applyPrefix('*')]); var keys = result.payload.map((RespType s) => s.payload) as Iterable; if (keys.isEmpty) return []; //result = await respCommands.client.writeArrayOfBulk(['MGET']..addAll(keys)); result = await respCommands.tier1.tier0.execute(['MGET', ...keys]); if (result.isArray) { return (result as List) .map>((RespType s) => json.decode(s.payload as String) as Map) .toList(); } else { // TODO: To be reviewed for handling none array objects return [json.decode(result.payload as String) as Map]; } } @override Future> read(String id, [Map? params]) async { var value = await respCommands.get(_applyPrefix(id)!); if (value == null) { throw AngelHttpException.notFound(message: 'No record found for ID $id'); } else { return json.decode(value) as Map; } } @override Future> create(Map? data, [Map? params]) async { String? id; if (data!['id'] != null) { id = data['id'] as String?; } else { var keyVar = await respCommands.tier1.tier0 .execute(['INCR', _applyPrefix('angel_redis:id')]); id = keyVar.payload.toString(); data = Map.from(data)..['id'] = id; } await respCommands.set(_applyPrefix(id)!, json.encode(data)); return data; } @override Future> modify(String id, Map? data, [Map? params]) async { var input = await (read(id)); input.addAll(data!); return await update(id, input, params); } @override Future> update(String id, Map? data, [Map? params]) async { data = Map.from(data!)..['id'] = id; await respCommands.set(_applyPrefix(id)!, json.encode(data)); return data; } @override Future> remove(String id, [Map? params]) async { var client = respCommands.tier1.tier0; await client.execute(['MULTI']); await client.execute(['GET', _applyPrefix(id)]); await client.execute(['DEL', _applyPrefix(id)]); var result = await client.execute(['EXEC']); var str = result.payload[0] as RespBulkString; if (str.payload == null) { throw AngelHttpException.notFound(message: 'No record found for ID $id'); } else { return json.decode(str.payload!) as Map; } } }