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: uptake persistence refactoring in server #1974

Draft
wants to merge 1 commit into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 11 additions & 11 deletions packages/at_secondary_server/lib/src/caching/cache_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ class AtCacheManager {
if (cachedKeyName.startsWith('cached:public:')) {
remoteKeyName = cachedKeyName.replaceAll('cached:public:', '');
remoteResponse =
await _remoteLookUp('all:$remoteKeyName', isHandShake: false);
await _remoteLookUp('all:$remoteKeyName', isHandShake: false);
} else if (cachedKeyName.startsWith('cached:$atSign')) {
remoteKeyName = cachedKeyName.replaceAll('cached:$atSign:', '');
remoteResponse =
await _remoteLookUp('all:$remoteKeyName', isHandShake: true);
await _remoteLookUp('all:$remoteKeyName', isHandShake: true);
} else {
throw IllegalArgumentException(
'remoteLookup called with invalid cachedKeyName $cachedKeyName');
Expand All @@ -132,7 +132,7 @@ class AtCacheManager {
} else {
logger.info(
'remoteLookUp: KeyNotFoundException while looking up $remoteKeyName'
' - but maintainCache is false, so leaving $cachedKeyName in cache');
' - but maintainCache is false, so leaving $cachedKeyName in cache');
}
rethrow;
}
Expand All @@ -150,7 +150,7 @@ class AtCacheManager {
} else {
logger.info(
'remoteLookUp: String value of "null" response while looking up $remoteKeyName'
' - but maintainCache is false, so leaving $cachedKeyName in cache');
' - but maintainCache is false, so leaving $cachedKeyName in cache');
}
throw KeyNotFoundException(
"remoteLookUp: remote atServer returned String value 'null' for $remoteKeyName");
Expand Down Expand Up @@ -295,9 +295,7 @@ class AtCacheManager {

// For everything other than 'cached:public:publickey@atSign' just put it into the key store
if (!cachedKeyName.startsWith('cached:public:publickey@')) {
await keyStore.put(cachedKeyName, atData,
time_to_refresh: atData.metaData!.ttr,
time_to_live: atData.metaData!.ttl);
await keyStore.put(cachedKeyName, atData);
return;
}

Expand All @@ -311,11 +309,12 @@ class AtCacheManager {
// so that we get the correct 'createdAt' value
// If the data has not changed, then we don't need to do anything
var otherAtSignWithoutTheAt =
cachedKeyName.replaceFirst('cached:public:publickey@', '');
cachedKeyName.replaceFirst('cached:public:publickey@', '');
try {
// 1) If it's not currently in the cache, then just update the cache and return
if (!keyStore.isKeyExists(cachedKeyName)) {
await keyStore.put(cachedKeyName, atData, time_to_refresh: -1);
await keyStore.put(cachedKeyName, atData,
metadata: Metadata()..ttr = -1);
return;
}

Expand Down Expand Up @@ -365,7 +364,8 @@ class AtCacheManager {

// Secondly, update the cache, and ensure that ttr is set to -1 (cache indefinitely)
await keyStore.remove(cachedKeyName);
await keyStore.put(cachedKeyName, atData, time_to_refresh: -1);
await keyStore.put(cachedKeyName, atData,
metadata: Metadata()..ttr = -1);
}
} catch (e, st) {
logger.severe(
Expand All @@ -389,4 +389,4 @@ class AtCacheManager {
}
return await outBoundClient.lookUp(key, handshake: isHandShake);
}
}
}
137 changes: 137 additions & 0 deletions packages/at_secondary_server/lib/src/metadata/at_metadata_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import 'package:at_persistence_secondary_server/at_persistence_secondary_server.dart';
import 'package:at_utils/at_logger.dart';

/// Builder class to build [AtMetaData] object.
class AtMetadataBuilder {
late final AtMetaData atMetaData;

/// We will constrain to millisecond precision because Hive only stores
/// [DateTime]s to millisecond precision - see https://github.com/hivedb/hive/issues/474
/// for details.
final DateTime currentUtcTimeToMillisecondPrecision =
DateTime.now().toUtcMillisecondsPrecision();

static final AtSignLogger logger = AtSignLogger('AtMetadataBuilder');

AtMetadataBuilder(
{String? atSign, AtMetaData? newMetaData, AtMetaData? existingMetaData})
: atMetaData = newMetaData ?? AtMetaData() {
// createdAt indicates the date and time of the key created.
// For a new key, the currentDateTime is set and remains unchanged
// on an update event.
atMetaData.createdAt =
existingMetaData?.createdAt ?? currentUtcTimeToMillisecondPrecision;
atMetaData.createdBy ??= atSign;
atMetaData.updatedBy = atSign;

// updatedAt indicates the date and time of the key updated.
atMetaData.updatedAt = currentUtcTimeToMillisecondPrecision;
atMetaData.status = 'active';

// sets newAtMetaData attributes if set. Otherwise fallback to existingMetaData attributes.
_copyMetadata(existingMetaData, newMetaData);

if (atMetaData.ttl != null && atMetaData.ttl! >= 0) {
setTTL(atMetaData.ttl, ttb: atMetaData.ttb);
}
if (atMetaData.ttb != null && atMetaData.ttb! >= 0) {
setTTB(atMetaData.ttb);
}
// If TTR is -1, cache the key forever.
if (atMetaData.ttr != null && atMetaData.ttr! > 0 || atMetaData.ttr == -1) {
setTTR(atMetaData.ttr);
}
}

// if existing metadata field is NOT null and new metadata field is null object, then set existing metadata field
// if existing metadata field is NOT null and new metadata field is not null object, then set new metadata field
// if existing metadata field is null and new metadata field is NOT null, then set new metadata field
// if existing metadata field is NOT null and new metadata field is null string, then set new metadata field (unset scenario)
void _copyMetadata(AtMetaData? existingMetaData, AtMetaData? newAtMetaData) {
atMetaData.ttl = _getOrDefault(newAtMetaData?.ttl, existingMetaData?.ttl);
atMetaData.ttb = newAtMetaData?.ttb ?? existingMetaData?.ttb;
atMetaData.ttr = newAtMetaData?.ttr ?? existingMetaData?.ttr;
atMetaData.isCascade =
newAtMetaData?.isCascade ?? existingMetaData?.isCascade;
atMetaData.isBinary = newAtMetaData?.isBinary ?? existingMetaData?.isBinary;
atMetaData.isEncrypted =
newAtMetaData?.isEncrypted ?? existingMetaData?.isEncrypted;
atMetaData.dataSignature = newAtMetaData?.dataSignature == "null"
? null
: newAtMetaData?.dataSignature ?? existingMetaData?.dataSignature;
atMetaData.sharedKeyEnc = newAtMetaData?.sharedKeyEnc == "null"
? null
: newAtMetaData?.sharedKeyEnc ?? existingMetaData?.sharedKeyEnc;
atMetaData.pubKeyCS = newAtMetaData?.pubKeyCS == "null"
? null
: newAtMetaData?.pubKeyCS ?? existingMetaData?.pubKeyCS;

atMetaData.encoding = newAtMetaData?.encoding == "null"
? null
: newAtMetaData?.encoding ?? existingMetaData?.encoding;
atMetaData.encKeyName = newAtMetaData?.encKeyName == "null"
? null
: newAtMetaData?.encKeyName ?? existingMetaData?.encKeyName;
atMetaData.encAlgo = newAtMetaData?.encAlgo == "null"
? null
: newAtMetaData?.encAlgo ?? existingMetaData?.encAlgo;
atMetaData.ivNonce = newAtMetaData?.ivNonce == "null"
? null
: newAtMetaData?.ivNonce ?? existingMetaData?.ivNonce;
atMetaData.skeEncKeyName = newAtMetaData?.skeEncKeyName == "null"
? null
: newAtMetaData?.skeEncKeyName ?? existingMetaData?.skeEncKeyName;
atMetaData.skeEncAlgo = newAtMetaData?.skeEncAlgo == "null"
? null
: newAtMetaData?.skeEncAlgo ?? existingMetaData?.skeEncAlgo;
atMetaData.version = newAtMetaData?.version ?? existingMetaData?.version;
}

int? _getOrDefault(int? newValue, int? existingValue) =>
newValue ?? existingValue;

void setTTL(int? ttl, {int? ttb}) {
if (ttl != null) {
atMetaData.ttl = ttl;
atMetaData.expiresAt = _getExpiresAt(
currentUtcTimeToMillisecondPrecision.millisecondsSinceEpoch, ttl,
ttb: ttb);
}
}

void setTTB(int? ttb) {
if (ttb != null) {
atMetaData.ttb = ttb;
atMetaData.availableAt = _getAvailableAt(
currentUtcTimeToMillisecondPrecision.millisecondsSinceEpoch, ttb);
logger
.finer('setTTB($ttb) - set availableAt to ${atMetaData.availableAt}');
}
}

void setTTR(int? ttr) {
if (ttr != null) {
atMetaData.ttr = ttr;
atMetaData.refreshAt =
_getRefreshAt(currentUtcTimeToMillisecondPrecision, ttr);
}
}

void setCCD(bool ccd) {
atMetaData.isCascade = ccd;
}

DateTime? _getAvailableAt(int epochNow, int ttb) =>
DateTime.fromMillisecondsSinceEpoch(epochNow + ttb).toUtc();

DateTime? _getExpiresAt(int epochNow, int ttl, {int? ttb}) {
if (ttl == 0) return null; // Key will not expire if TTL is 0
var expiresAt = epochNow + ttl + (ttb ?? 0);
return DateTime.fromMillisecondsSinceEpoch(expiresAt).toUtc();
}

DateTime? _getRefreshAt(DateTime today, int ttr) =>
ttr == -1 ? null : today.add(Duration(seconds: ttr));

AtMetaData build() => atMetaData;
}
11 changes: 6 additions & 5 deletions packages/at_secondary_server/lib/src/utils/secondary_util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:at_persistence_secondary_server/at_persistence_secondary_server.dart';
import 'package:at_utils/at_logger.dart';
import 'package:crypton/crypton.dart';
import 'package:at_commons/at_commons.dart';

class SecondaryUtil {
static var logger = AtSignLogger('Secondary_Util');
Expand All @@ -16,13 +17,13 @@ class SecondaryUtil {
atData.data = value;

var secondaryPersistenceStore =
SecondaryPersistenceStoreFactory.getInstance()
.getSecondaryPersistenceStore(atSign)!;
SecondaryPersistenceStoreFactory.getInstance()
.getSecondaryPersistenceStore(atSign)!;
var keystoreManager =
secondaryPersistenceStore.getSecondaryKeyStoreManager()!;
secondaryPersistenceStore.getSecondaryKeyStoreManager()!;
SecondaryKeyStore keyStore = keystoreManager.getKeyStore();
await keyStore.put('public:$key', atData,
time_to_live: 60 * 1000); //expire in 1 min
metadata: Metadata()..ttl = 60 * 1000); //expire in 1 min
}

static List<String> getSecondaryInfo(String url) {
Expand Down Expand Up @@ -197,4 +198,4 @@ class SecondaryUtil {
}
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class FromVerbHandler extends AbstractVerbHandler {
//store key with private/public prefix, sessionId and fromAtSign
await keyStore.put(
'$keyPrefix${atConnectionMetadata.sessionID}$fromAtSign', atData,
time_to_live: 60 * 1000); //expire in 1 min
metadata: Metadata()..ttl = 60 * 1000); //expire in 1 min
response.data =
'$responsePrefix${atConnectionMetadata.sessionID}$fromAtSign:$proof';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:at_secondary/src/server/at_secondary_impl.dart';
import 'package:at_secondary/src/utils/notification_util.dart';
import 'package:at_secondary/src/utils/secondary_util.dart';
import 'package:at_secondary/src/verb/handler/abstract_verb_handler.dart';
import 'package:at_secondary/src/metadata/at_metadata_builder.dart';
import 'package:at_secondary/src/verb/verb_enum.dart';
import 'package:at_server_spec/at_server_spec.dart';
import 'package:at_server_spec/at_verb_spec.dart';
Expand Down Expand Up @@ -160,7 +161,7 @@ class NotifyVerbHandler extends AbstractVerbHandler {
atMetadata = await keyStore.getMeta(cachedNotificationKey);
}
var metadata = AtMetadataBuilder(
newAtMetaData: atNotificationBuilder.atMetaData,
newMetaData: atNotificationBuilder.atMetaData,
existingMetaData: atMetadata)
.build();
cachedKeyCommitId = await _storeCachedKeys(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import 'dart:collection';

import 'package:at_commons/at_commons.dart';
import 'package:at_persistence_secondary_server/at_persistence_secondary_server.dart';
import 'package:at_secondary/src/metadata/at_metadata_builder.dart';
import 'package:at_secondary/src/notification/stats_notification_service.dart';
import 'package:at_secondary/src/server/at_secondary_impl.dart';
import 'package:at_secondary/src/verb/handler/abstract_update_verb_handler.dart';
import 'package:at_server_spec/at_server_spec.dart';

Expand All @@ -25,13 +27,25 @@ class UpdateMetaVerbHandler extends AbstractUpdateVerbHandler {
HashMap<String, String?> verbParams,
InboundConnection atConnection) async {
var updatePreProcessResult =
await super.preProcessAndNotify(response, verbParams, atConnection);
await super.preProcessAndNotify(response, verbParams, atConnection);
final atSign = AtSecondaryServerImpl.getInstance().currentAtSign;
AtData? existingData;

try {
existingData = await keyStore.get(updatePreProcessResult.atKey);
} on KeyNotFoundException {
// do nothing
}
var newMetadata = AtMetadataBuilder(
newMetaData: updatePreProcessResult.atData.metaData!,
existingMetaData: existingData?.metaData,
atSign: atSign)
.build();
// update the key in data store
logger.finer(
'calling keyStore.putMeta(${updatePreProcessResult.atKey}, ${updatePreProcessResult.atData.metaData!}');
var result = await keyStore.putMeta(
updatePreProcessResult.atKey, updatePreProcessResult.atData.metaData!);
'calling keyStore.putMeta(${updatePreProcessResult.atKey}, $newMetadata');
var result =
await keyStore.putMeta(updatePreProcessResult.atKey, newMetadata);
response.data = result?.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class UpdateVerbHandler extends AbstractUpdateVerbHandler {
HashMap<String, String?> verbParams,
InboundConnection atConnection) async {
var updatePreProcessResult =
await super.preProcessAndNotify(response, verbParams, atConnection);
await super.preProcessAndNotify(response, verbParams, atConnection);

logger.finer(
'calling keyStore.put(${updatePreProcessResult.atKey}, ${updatePreProcessResult.atData}');
Expand All @@ -47,25 +47,11 @@ class UpdateVerbHandler extends AbstractUpdateVerbHandler {
// update the key in data store
var result = await keyStore.put(
updatePreProcessResult.atKey, updatePreProcessResult.atData,
time_to_live: updatePreProcessResult.atData.metaData!.ttl,
time_to_born: updatePreProcessResult.atData.metaData!.ttb,
time_to_refresh: updatePreProcessResult.atData.metaData!.ttr,
isCascade: updatePreProcessResult.atData.metaData!.isCascade,
isBinary: updatePreProcessResult.atData.metaData!.isBinary,
isEncrypted: updatePreProcessResult.atData.metaData!.isEncrypted,
dataSignature: updatePreProcessResult.atData.metaData!.dataSignature,
sharedKeyEncrypted:
updatePreProcessResult.atData.metaData!.sharedKeyEnc,
publicKeyChecksum: updatePreProcessResult.atData.metaData!.pubKeyCS,
encoding: updatePreProcessResult.atData.metaData!.encoding,
encKeyName: updatePreProcessResult.atData.metaData!.encKeyName,
encAlgo: updatePreProcessResult.atData.metaData!.encAlgo,
ivNonce: updatePreProcessResult.atData.metaData!.ivNonce,
skeEncKeyName: updatePreProcessResult.atData.metaData!.skeEncKeyName,
skeEncAlgo: updatePreProcessResult.atData.metaData!.skeEncAlgo);
metadata:
updatePreProcessResult.atData.metaData!.toCommonsMetadata());
response.data = result?.toString();
} catch (e, st) {
logger.warning('$e\n$st');
}
}
}
}
14 changes: 13 additions & 1 deletion packages/at_secondary_server/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ dependencies:
basic_utils: 5.7.0
ecdsa: 0.1.0
encrypt: 5.0.3
at_commons: 4.0.9
at_commons: 4.0.10
at_utils: 3.0.16
at_chops: 2.0.0
at_lookup: 3.0.47
Expand All @@ -34,6 +34,18 @@ dependencies:
yaml: 3.1.2
logging: 1.2.0

dependency_overrides:
at_persistence_secondary_server:
git:
url: https://github.com/atsign-foundation/at_server/
path: packages/at_persistence_secondary_server
ref: secondary_persistence_impl_new
at_persistence_spec:
git:
url: https://github.com/atsign-foundation/at_server/
path: packages/at_persistence_spec
ref: persistence_spec_refactoring

dev_dependencies:
test: ^1.24.4
coverage: ^1.6.1
Expand Down
Loading