Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/enhance marshaller data structure #168

Merged
merged 41 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f4f49b3
feat(marshaller): define cache fragments
LeadcodeDev Jul 15, 2024
e069c13
feat(marshaller): implement cache serialization and add cache seriali…
LeadcodeDev Jul 15, 2024
526e13e
feat(marshaller): implement delete methods
LeadcodeDev Jul 15, 2024
cd03158
feat(marshaller): register roles when guild create is trigger
LeadcodeDev Jul 15, 2024
a9c05ad
feat(marshaller): compute category channels
LeadcodeDev Jul 15, 2024
fd06949
feat(marshaller): add cache serialization cases
LeadcodeDev Jul 16, 2024
4b1b542
feat(marshaller): create server serialization from cache
LeadcodeDev Jul 16, 2024
a659ab9
feat(marshaller): remove duplicated action
LeadcodeDev Jul 16, 2024
bcf8866
feat(marshaller): enhance marshaller to deep key/value
LeadcodeDev Jul 21, 2024
e969310
feat(marshaller): enhance role cache serialization
LeadcodeDev Jul 21, 2024
060296a
feat(marshaller): enhance member cache serialization
LeadcodeDev Jul 21, 2024
8343c6f
feat(marshaller): enhance emoji cache serialization
LeadcodeDev Jul 21, 2024
12bec12
feat(marshaller): enhance channel permission cache serialization
LeadcodeDev Jul 21, 2024
0afabeb
feat(marshaller): enhance global command cache serialization
LeadcodeDev Jul 21, 2024
a74d0d9
feat(marshaller): enhance member and channel cache serialization
LeadcodeDev Jul 21, 2024
da85061
feat(marshaller): remove dead code
LeadcodeDev Jul 21, 2024
f74ca66
feat(marshaller): enhance user deserialize
LeadcodeDev Jul 21, 2024
93ffc51
feat(marshaller): implement sticker serialization from cache
LeadcodeDev Jul 21, 2024
0c57a58
feat(marshaller): implement server subscription serialization from cache
LeadcodeDev Jul 21, 2024
44ab7bc
feat(marshaller): implement server role serialization from cache
LeadcodeDev Jul 21, 2024
95f505e
feat(marshaller): enhance message serializers
LeadcodeDev Jul 21, 2024
edcb9f8
feat(packets): enhance presence member finder
LeadcodeDev Jul 21, 2024
a202289
feat(datastore): implement cacheKey and enhance parts of datastore
LeadcodeDev Jul 21, 2024
2cda0c9
feat(packets): apply newer serialization in channel create packet
LeadcodeDev Jul 21, 2024
fe9d1b4
feat(packets): apply newer serialization in channel update packet
LeadcodeDev Jul 21, 2024
cd4ac12
feat(packets): apply newer serialization in channel pin update packet
LeadcodeDev Jul 21, 2024
05e8dac
feat(packets): apply newer serialization in channel update packet
LeadcodeDev Jul 21, 2024
1315352
feat(packets): apply newer serialization in guild create packet
LeadcodeDev Jul 21, 2024
d6bd1b3
feat(packets): apply newer serialization in guild delete packet
LeadcodeDev Jul 21, 2024
12cd0d1
feat(packets): apply newer serialization in guild emojis update packet
LeadcodeDev Jul 21, 2024
f7c7483
feat(packets): apply newer serialization in member add packet
LeadcodeDev Jul 21, 2024
391d041
feat(packets): apply newer serialization in member chunk packet
LeadcodeDev Jul 21, 2024
f533a05
feat(packets): apply newer serialization in member remove packet
LeadcodeDev Jul 21, 2024
340740c
feat(packets): apply newer serialization in member update packet
LeadcodeDev Jul 21, 2024
5e49046
feat(marshaller): enhance member serialization with cached keys
LeadcodeDev Jul 21, 2024
ccd97ab
feat(packets): apply newer serialization in role delete packet
LeadcodeDev Jul 21, 2024
80089c3
feat(packets): apply newer serialization in role update packet
LeadcodeDev Jul 21, 2024
28f7726
feat(packets): apply newer serialization in server update packet
LeadcodeDev Jul 21, 2024
5f09326
feat(packets): add missing guild_id
LeadcodeDev Jul 21, 2024
0a79df2
feat(packets): apply newer serialization in message create packet
LeadcodeDev Jul 21, 2024
7e893f3
feat(packets): apply newer serialization in presence update packet
LeadcodeDev Jul 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions lib/api/common/activity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ final class Activity {

factory Activity.fromJson(Map<String, dynamic> json) {
return Activity(
name: json['name'],
type: ActivityType.values[json['type']],
url: json['url'],
createdAt: DateTime.fromMillisecondsSinceEpoch(json['created_at']),
details: json['details'],
state: json['state'],
emoji: Helper.createOrNull(field: json['emoji'], fn: () => ActivityEmoji(name: json['name'], id: json['id'], animated: json['animated'] ?? false))
);
name: json['name'],
type: ActivityType.values.firstWhere((element) => element.value == json['type'],
orElse: () => ActivityType.unknown),
url: json['url'],
createdAt: DateTime.fromMillisecondsSinceEpoch(json['created_at']),
details: json['details'],
state: json['state'],
emoji: Helper.createOrNull(
field: json['emoji'],
fn: () => ActivityEmoji(
name: json['name'], id: json['id'], animated: json['animated'] ?? false)));
}
}
62 changes: 59 additions & 3 deletions lib/api/common/channel_properties.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,22 @@ final class ChannelProperties {
required this.defaultForumLayout,
});

static Future<ChannelProperties> make(
static Future<ChannelProperties> serializeRemote(
MarshallerContract marshaller, Map<String, dynamic> element) async {
final permissionOverwrites = await Helper.createOrNullAsync(
field: element['permission_overwrites'],
fn: () async => Future.wait(
List.from(element['permission_overwrites'])
.map((json) async =>
marshaller.serializers.channelPermissionOverwrite.serialize(json))
marshaller.serializers.channelPermissionOverwrite.serializeRemote(json))
.toList(),
));

final recipients = await Helper.createOrNullAsync(
field: element['recipients'],
fn: () async => Future.wait(
List.from(element['recipients'])
.map((json) async => marshaller.serializers.user.serialize(json))
.map((json) async => marshaller.serializers.user.serializeRemote(json))
.toList(),
));

Expand Down Expand Up @@ -131,4 +131,60 @@ final class ChannelProperties {
defaultForumLayout: element['default_forum_layout'],
);
}

static Future<ChannelProperties> serializeCache(
MarshallerContract marshaller, Map<String, dynamic> element) async {
final permissionOverwrites = await Helper.createOrNullAsync(
field: element['permission_overwrites'],
fn: () async => Future.wait(
List.from(element['permission_overwrites'])
.map((json) async =>
marshaller.serializers.channelPermissionOverwrite.serializeRemote(json))
.toList(),
));

final recipients = await Helper.createOrNullAsync(
field: element['recipients'],
fn: () async => Future.wait(
List.from(element['recipients'])
.map((json) async => marshaller.serializers.user.serializeRemote(json))
.toList(),
));

return ChannelProperties(
id: Snowflake(element['id']),
type: findInEnum(ChannelType.values, element['type']),
name: element['name'],
description: element['description'],
guildId: Helper.createOrNull(
field: element['guild_id'], fn: () => Snowflake(element['guild_id'])),
categoryId: Helper.createOrNull(
field: element['parent_id'], fn: () => Snowflake(element['parent_id'])),
position: element['position'],
nsfw: element['nsfw'] ?? false,
lastMessageId: Helper.createOrNull(
field: element['last_message_id'], fn: () => Snowflake(element['last_message_id'])),
bitrate: element['bitrate'],
userLimit: element['user_limit'],
rateLimitPerUser: element['rate_limit_per_user'],
recipients: recipients ?? [],
icon: element['icon'],
ownerId: element['owner_id'],
applicationId: element['application_id'],
lastPinTimestamp: element['last_pin_timestamp'],
rtcRegion: element['rtc_region'],
videoQualityMode: element['video_quality_mode'],
messageCount: element['message_count'],
memberCount: element['member_count'],
defaultAutoArchiveDuration: element['default_auto_archive_duration'],
permissions: permissionOverwrites,
flags: element['flags'],
totalMessageSent: element['total_message_sent'],
available: element['available'],
appliedTags: element['applied_tags'] ?? [],
defaultReactions: element['default_reactions'],
defaultSortOrder: element['default_sort_order'],
defaultForumLayout: element['default_forum_layout'],
);
}
}
2 changes: 1 addition & 1 deletion lib/api/common/message_properties.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class MessageProperties<T extends Channel> {
factory MessageProperties.fromJson(T channel, Map<String, dynamic> json) {
final embedSerializer = ioc.resolve<MarshallerContract>().serializers.embed;
final embeds = List.from(json['embeds'])
.map((element) => embedSerializer.serialize(element) as MessageEmbed)
.map((element) => embedSerializer.serializeRemote(element) as MessageEmbed)
.toList();

return MessageProperties(
Expand Down
7 changes: 5 additions & 2 deletions lib/api/common/types/activity_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ enum ActivityType implements EnhancedEnum<int> {
listening(2),
watching(3),
custom(4),
competing(5);
competing(5),
unknown(-1);

@override
final int value;

const ActivityType(this.value);
}
}
8 changes: 5 additions & 3 deletions lib/api/server/channels/server_announcement_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ final class ServerAnnouncementChannel extends ServerChannel {

bool get isNsfw => _properties.nsfw;

ServerCategoryChannel? category;

@override
Snowflake get guildId => _properties.guildId!;

ServerAnnouncementChannel(this._properties, {required this.category})
Snowflake? get categoryId => _properties.categoryId;

late final ServerCategoryChannel? category;

ServerAnnouncementChannel(this._properties)
: _methods = ChannelMethods(_properties.id);

Future<void> setName(String name, {String? reason}) => _methods.setName(name, reason);
Expand Down
6 changes: 4 additions & 2 deletions lib/api/server/channels/server_stage_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ final class ServerStageChannel extends ServerChannel {

String? get description => _properties.description;

late final ServerCategoryChannel? category;

@override
Snowflake get guildId => _properties.guildId!;

Snowflake? get categoryId => _properties.categoryId;

late final ServerCategoryChannel? category;

ServerStageChannel(this._properties) : _methods = ChannelMethods(_properties.id);

Future<void> setName(String name, {String? reason}) => _methods.setName(name, reason);
Expand Down
6 changes: 4 additions & 2 deletions lib/api/server/channels/server_text_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ final class ServerTextChannel extends ServerChannel {

String? get description => _properties.description;

late final ServerCategoryChannel? category;

@override
Snowflake get guildId => _properties.guildId!;

Snowflake? get categoryId => _properties.categoryId;

late final ServerCategoryChannel? category;

ServerTextChannel(this._properties) : _methods = ChannelMethods(_properties.id);

Future<void> setName(String name, {String? reason}) => _methods.setName(name, reason);
Expand Down
5 changes: 5 additions & 0 deletions lib/api/server/channels/server_voice_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:mineral/api/common/managers/message_manager.dart';
import 'package:mineral/api/common/snowflake.dart';
import 'package:mineral/api/common/types/channel_type.dart';
import 'package:mineral/api/common/video_quality.dart';
import 'package:mineral/api/server/channels/server_category_channel.dart';
import 'package:mineral/api/server/channels/server_channel.dart';
import 'package:mineral/api/server/server_message.dart';

Expand Down Expand Up @@ -32,6 +33,10 @@ final class ServerVoiceChannel extends ServerChannel {
@override
Snowflake get guildId => _properties.guildId!;

Snowflake? get categoryId => _properties.categoryId;

late final ServerCategoryChannel? category;

ServerVoiceChannel(this._properties) : _methods = ChannelMethods(_properties.id);

Future<void> setName(String name, {String? reason}) => _methods.setName(name, reason);
Expand Down
45 changes: 13 additions & 32 deletions lib/api/server/managers/channel_manager.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import 'package:mineral/api/common/snowflake.dart';
import 'package:mineral/api/common/types/channel_type.dart';
import 'package:mineral/api/server/channels/server_channel.dart';
import 'package:mineral/api/server/channels/server_text_channel.dart';
import 'package:mineral/api/server/channels/server_voice_channel.dart';
import 'package:mineral/infrastructure/internals/marshaller/marshaller.dart';

enum _ServerNamedChannel {
afkChannel,
Expand All @@ -15,17 +13,25 @@ enum _ServerNamedChannel {
}

final class ChannelManager {
final Map<_ServerNamedChannel, Snowflake?> _namedChannels;
final Map<Snowflake, ServerChannel> _channels;

ChannelManager(this._channels, this._namedChannels);
final Map<_ServerNamedChannel, Snowflake?> _namedChannels = {};
final Map<Snowflake, ServerChannel> _channels = {};

ChannelManager(Map<String, dynamic> json) {
_namedChannels..putIfAbsent(
_ServerNamedChannel.afkChannel, () => json['afk_channel_id'])..putIfAbsent(
_ServerNamedChannel.systemChannel, () => json['system_channel_id'])..putIfAbsent(
_ServerNamedChannel.rulesChannel, () => json['rules_channel_id'])..putIfAbsent(
_ServerNamedChannel
.publicUpdatesChannel, () => json['public_updates_channel_id'])..putIfAbsent(
_ServerNamedChannel.safetyAlertsChannel, () => json['safety_alerts_channel_id']);
}

Map<Snowflake, ServerChannel> get list => _channels;

T? getOrNull<T extends ServerChannel>(Snowflake? id) => _channels[id] as T?;

T getOrFail<T extends ServerChannel>(String id) =>
_channels.values.firstWhere((element) => element.id == id,
_channels.values.firstWhere((element) => element.id.value == id,
orElse: () => throw Exception('Channel not found')) as T;

ServerVoiceChannel? get afkChannel =>
Expand All @@ -45,29 +51,4 @@ final class ChannelManager {

ServerTextChannel? get widgetChannel =>
getOrNull<ServerTextChannel>(_namedChannels[_ServerNamedChannel.widgetChannel]);

static Future<ChannelManager> fromJson(
{required MarshallerContract marshaller,
required String guildId,
required Map<String, dynamic> json}) async {
final awaitedChannels = await Future.wait(List.from(json['channels'])
.where((element) => element['type'] != ChannelType.guildCategory.value)
.map((element) async => marshaller.serializers.channels.serialize({
...element,
'guild_id': guildId,
})));

final Map<Snowflake, ServerChannel> channels = awaitedChannels.nonNulls.fold(
{}, (previousValue, element) => {...previousValue, element.id: element as ServerChannel});

final Map<_ServerNamedChannel, Snowflake?> namedChannels = {
_ServerNamedChannel.afkChannel: json['afk_channel_id'],
_ServerNamedChannel.systemChannel: json['system_channel_id'],
_ServerNamedChannel.rulesChannel: json['rules_channel_id'],
_ServerNamedChannel.publicUpdatesChannel: json['public_updates_channel_id'],
_ServerNamedChannel.safetyAlertsChannel: json['safety_alerts_channel_id'],
};

return ChannelManager(channels, namedChannels);
}
}
2 changes: 1 addition & 1 deletion lib/api/server/managers/emoji_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class EmojiManager {
factory EmojiManager.fromJson(MarshallerContract marshaller,
{required List<Role> roles, required List<dynamic> payload}) {
return EmojiManager(Map<Snowflake, Emoji>.from(payload.fold({}, (value, element) {
final emoji = marshaller.serializers.emojis.serialize({
final emoji = marshaller.serializers.emojis.serializeRemote({
'guildRoles': roles,
...element,
}) as Emoji;
Expand Down
2 changes: 1 addition & 1 deletion lib/api/server/managers/sticker_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ final class StickerManager {

factory StickerManager.fromJson(MarshallerContract marshaller, List<dynamic> payload) {
final Map<Snowflake, Sticker> stickers = payload.fold({}, (value, element) {
final sticker = marshaller.serializers.sticker.serialize(element) as Sticker;
final sticker = marshaller.serializers.sticker.serializeRemote(element) as Sticker;
return {...value, sticker.id: sticker};
});

Expand Down
10 changes: 5 additions & 5 deletions lib/domains/commands/command_interaction_dispatcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ final class CommandInteractionDispatcher implements InteractionDispatcherContrac
final command = _interactionManager.commandsHandler.firstWhere((command) => command.$1 == data['data']['name']);

final commandContext = switch (data['data']['guild_id']) {
String() => await _marshaller.serializers.guildCommandContext.serialize(data),
_ => await _marshaller.serializers.globalCommandContext.serialize(data),
String() => await _marshaller.serializers.guildCommandContext.serializeRemote(data),
_ => await _marshaller.serializers.globalCommandContext.serializeRemote(data),
};

final Map<Symbol, dynamic> options = {};
Expand All @@ -69,10 +69,10 @@ final class CommandInteractionDispatcher implements InteractionDispatcherContrac
options[Symbol(option['name'])] = switch(type) {
CommandOptionType.user => switch (commandContext) {
ServerCommandContext() => await _marshaller.dataStore.member.getMember(guildId: commandContext.server.id, memberId: option['value']),
_ => _marshaller.serializers.user.serialize(option['value']),
_ => _marshaller.serializers.user.serializeRemote(option['value']),
},
CommandOptionType.channel => await _marshaller.serializers.channels.serialize(option['value']),
CommandOptionType.role => await _marshaller.serializers.role.serialize(option['value']),
CommandOptionType.channel => await _marshaller.serializers.channels.serializeRemote(option['value']),
CommandOptionType.role => await _marshaller.serializers.role.serializeRemote(option['value']),
// TODO attachement
_ => option['value'],
};
Expand Down
14 changes: 7 additions & 7 deletions lib/infrastructure/internals/cache/cache_provider_contract.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'dart:async';

import 'package:mineral/api/common/snowflake.dart';
import 'package:mineral/infrastructure/services/logger/logger.dart';

abstract interface class CacheProviderContract {
Expand All @@ -11,13 +10,14 @@ abstract interface class CacheProviderContract {
FutureOr<void> init();

Future<int> length();
Future<Map<String, dynamic>> getInternalValues();
Future<List<Map<String, dynamic>>> getAll();
Future<Map<String, dynamic>?> get(Snowflake? key);
Future<Map<String, dynamic>> getOrFail(Snowflake key, { Exception Function()? onFail });
Future<bool> has(Snowflake key);
Future<void> put<T>(Snowflake key, T object);
Future<void> remove(Snowflake key);
Future<void> removeMany(List<Snowflake> key);
FutureOr<Map<String, dynamic>?> get(String? key);
FutureOr<Map<String, dynamic>> getOrFail(String key, { Exception Function()? onFail });
Future<bool> has(String key);
Future<void> put<T>(String key, T object);
Future<void> remove(String key);
Future<void> removeMany(List<String> key);
Future<void> clear();

Future<void> dispose();
Expand Down
Loading