0.3.16-pre.007
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-store-postgres-lib/src/raw_transaction.rs
|
||||
// version: 13
|
||||
// version: 14
|
||||
|
||||
pub(crate) mod cursor;
|
||||
|
||||
@@ -12,6 +12,7 @@ const GET_TOMBSTONE_SQL: &str = "SELECT signature, slot::text AS slot_text, bloc
|
||||
const GET_TRANSACTION_SQL: &str = "SELECT transaction_row.signature, transaction_row.slot::text AS slot_text, transaction_row.block_time_unix_millis, transaction_row.format_id, transaction_row.format_version, transaction_row.content_hash, transaction_row.payload, transaction_row.retention_state, archive_row.payload AS archive_payload FROM ksp_raw_transactions AS transaction_row LEFT JOIN ksp_raw_transaction_archive_payloads AS archive_row ON archive_row.signature = transaction_row.signature WHERE transaction_row.signature = $1";
|
||||
const INSERT_ARCHIVE_PAYLOAD_SQL: &str = "INSERT INTO ksp_raw_transaction_archive_payloads (signature, payload) VALUES ($1, $2)";
|
||||
const INSERT_OBSERVATION_SQL: &str = "INSERT INTO ksp_raw_transaction_observations (observation_key, transaction_signature, provider, protocol, acquisition_method, origin, received_at_unix_millis, capture_session_id, commitment, endpoint_id, filter_id, observed_at_unix_millis, source_payload_hash, source_payload_size_bytes) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) ON CONFLICT (observation_key) DO NOTHING RETURNING observation_key";
|
||||
const INSERT_TRANSACTION_CONFLICT_SQL: &str = "INSERT INTO ksp_raw_transaction_conflicts (transaction_signature, status, revision, canonical_variant_id, incoming_variant_id, latest_relation, latest_reason_code, created_at_unix_millis, updated_at_unix_millis) VALUES ($1, 'open', 1, $2::TEXT::NUMERIC, $3::TEXT::NUMERIC, $4, $5, $6, $6)";
|
||||
const INSERT_TRANSACTION_SQL: &str = "INSERT INTO ksp_raw_transactions (signature, slot, block_time_unix_millis, format_id, format_version, content_hash, payload, retention_state) VALUES ($1, $2::TEXT::NUMERIC, $3, $4, $5, $6, $7, 'full') ON CONFLICT (signature) DO NOTHING RETURNING signature";
|
||||
const INSERT_TRANSACTION_VARIANT_LINK_SQL: &str = "INSERT INTO ksp_raw_transaction_observation_variants (observation_key, transaction_signature, variant_id, linked_at_unix_millis) VALUES ($1, $2, $3::TEXT::NUMERIC, $4) RETURNING observation_key";
|
||||
const INSERT_TRANSACTION_VARIANT_SELECTOR_SQL: &str = "INSERT INTO ksp_raw_transaction_canonical_selectors (transaction_signature, canonical_variant_id, canonical_revision, updated_at_unix_millis) VALUES ($1, $2::TEXT::NUMERIC, 1, $3)";
|
||||
@@ -25,6 +26,7 @@ const LIST_TRANSACTIONS_DESC_SQL: &str = "SELECT signature, slot::text AS slot_t
|
||||
const LOCK_OBSERVATION_SQL: &str = "SELECT observation_key, transaction_signature, provider, protocol, acquisition_method, origin, received_at_unix_millis, capture_session_id, commitment, endpoint_id, filter_id, observed_at_unix_millis, source_payload_hash, source_payload_size_bytes FROM ksp_raw_transaction_observations WHERE observation_key = $1 FOR UPDATE";
|
||||
const LOCK_RETENTION_TRANSACTION_SQL: &str =
|
||||
"SELECT block_time_unix_millis, payload, retention_state FROM ksp_raw_transactions WHERE signature = $1 FOR UPDATE";
|
||||
const LOCK_TRANSACTION_CONFLICT_SQL: &str = "SELECT status, revision::TEXT AS revision_text, canonical_variant_id::TEXT AS canonical_variant_id_text, incoming_variant_id::TEXT AS incoming_variant_id_text, latest_relation, latest_reason_code, created_at_unix_millis, updated_at_unix_millis FROM ksp_raw_transaction_conflicts WHERE transaction_signature = $1 FOR UPDATE";
|
||||
const LOCK_TRANSACTION_SQL: &str = "SELECT signature, slot::text AS slot_text, block_time_unix_millis, format_id, format_version, content_hash, payload, retention_state, NULL::BYTEA AS archive_payload FROM ksp_raw_transactions WHERE signature = $1 FOR UPDATE";
|
||||
const RAW_TRANSACTION_CONTENT_CONFLICT_META_FIELDS: [&str; 15] = [
|
||||
"err",
|
||||
@@ -59,6 +61,7 @@ const UPDATE_ARCHIVED_TRANSACTION_SQL: &str =
|
||||
const UPDATE_CANONICAL_TRANSACTION_PROJECTION_SQL: &str = "UPDATE ksp_raw_transactions SET slot = $2::TEXT::NUMERIC, block_time_unix_millis = $3, format_id = $4, format_version = $5, content_hash = $6, payload = $7, retention_state = 'full' WHERE signature = $1";
|
||||
const UPDATE_PURGED_TRANSACTION_SQL: &str = "UPDATE ksp_raw_transactions SET block_time_unix_millis = NULL, payload = NULL, retention_state = 'purged' WHERE signature = $1 AND retention_state = 'archived'";
|
||||
const UPDATE_REHYDRATED_TRANSACTION_VARIANT_SQL: &str = "UPDATE ksp_raw_transaction_variants SET block_time_unix_millis = $3, payload = $4, retention_state = 'full' WHERE transaction_signature = $1 AND variant_id = $2::TEXT::NUMERIC";
|
||||
const UPDATE_TRANSACTION_CONFLICT_SQL: &str = "UPDATE ksp_raw_transaction_conflicts SET status = 'open', revision = $2::TEXT::NUMERIC, canonical_variant_id = $3::TEXT::NUMERIC, incoming_variant_id = $4::TEXT::NUMERIC, latest_relation = $5, latest_reason_code = $6, updated_at_unix_millis = $7 WHERE transaction_signature = $1 AND revision = $8::TEXT::NUMERIC";
|
||||
const UPDATE_TRANSACTION_VARIANT_SELECTOR_SQL: &str = "UPDATE ksp_raw_transaction_canonical_selectors SET canonical_variant_id = $4::TEXT::NUMERIC, canonical_revision = $5::TEXT::NUMERIC, updated_at_unix_millis = $6 WHERE transaction_signature = $1 AND canonical_variant_id = $2::TEXT::NUMERIC AND canonical_revision = $3::TEXT::NUMERIC";
|
||||
const UPDATE_TRANSACTION_VARIANT_TO_FULL_SQL: &str = "UPDATE ksp_raw_transaction_variants SET payload = $8, retention_state = 'full' WHERE transaction_signature = $1 AND variant_id = $2::TEXT::NUMERIC AND slot = $3::TEXT::NUMERIC AND block_time_unix_millis IS NOT DISTINCT FROM $4 AND format_id = $5 AND format_version = $6 AND content_hash = $7 AND ((retention_state = 'archived' AND payload IS NULL) OR (retention_state = 'full' AND payload = $8))";
|
||||
|
||||
@@ -701,42 +704,86 @@ pub(crate) async fn persist_raw_transaction_acquisition(
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let (entity_outcome, observed_variant_id, canonical_promotion) = if inserted {
|
||||
(ksp_store_api::RawEntityWriteOutcome::Inserted, canonical_variant_id, std::option::Option::None)
|
||||
let (entity_outcome, observed_variant_id, transaction_variant_outcome, canonical_promotion, quarantined_conflict) = if inserted {
|
||||
(
|
||||
ksp_store_api::RawEntityWriteOutcome::Inserted,
|
||||
canonical_variant_id,
|
||||
ksp_store_api::RawTransactionVariantWriteOutcome::InsertedCanonical,
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
)
|
||||
} else {
|
||||
let comparison_result = compare_existing_transaction(network, locked.clone(), &raw_transaction);
|
||||
let comparison = match comparison_result {
|
||||
let comparison = match compare_existing_transaction(network, locked.clone(), &raw_transaction) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => {
|
||||
if error.kind() == crate::PostgresBackendErrorKind::Conflict && error.phase() == "raw_acquisition_content_conflict" {
|
||||
log_raw_transaction_content_conflict_provenance(&sql_transaction, network, &observation).await;
|
||||
}
|
||||
return std::result::Result::Err(error);
|
||||
},
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
match comparison {
|
||||
ExistingTransactionMatch::Active => (ksp_store_api::RawEntityWriteOutcome::AlreadyPresent, canonical_variant_id, std::option::Option::None),
|
||||
ExistingTransactionMatch::Active => (
|
||||
ksp_store_api::RawEntityWriteOutcome::AlreadyPresent,
|
||||
canonical_variant_id,
|
||||
ksp_store_api::RawTransactionVariantWriteOutcome::ObservedExact,
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
),
|
||||
ExistingTransactionMatch::ActiveCompatibleLessComplete => {
|
||||
let variant_result = persist_or_reuse_native_transaction_variant(&sql_transaction, &raw_transaction, linked_at).await;
|
||||
let variant_id = match variant_result {
|
||||
let variant_id = match persist_or_reuse_native_transaction_variant(&sql_transaction, &raw_transaction, linked_at).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
(ksp_store_api::RawEntityWriteOutcome::AlreadyPresent, variant_id, std::option::Option::None)
|
||||
(
|
||||
ksp_store_api::RawEntityWriteOutcome::AlreadyPresent,
|
||||
variant_id,
|
||||
ksp_store_api::RawTransactionVariantWriteOutcome::ObservedCompatibleLessComplete,
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
)
|
||||
},
|
||||
ExistingTransactionMatch::ActiveCompatibleMoreComplete => {
|
||||
let variant_result = persist_or_reuse_native_transaction_variant(&sql_transaction, &raw_transaction, linked_at).await;
|
||||
let variant_id = match variant_result {
|
||||
let variant_id = match persist_or_reuse_native_transaction_variant(&sql_transaction, &raw_transaction, linked_at).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let promotion_result =
|
||||
promote_more_complete_transaction_variant(&sql_transaction, &locked, &raw_transaction, canonical_variant_id, variant_id, linked_at).await;
|
||||
let promotion = match promotion_result {
|
||||
let promotion =
|
||||
match promote_more_complete_transaction_variant(&sql_transaction, &locked, &raw_transaction, canonical_variant_id, variant_id, linked_at)
|
||||
.await
|
||||
{
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
(
|
||||
ksp_store_api::RawEntityWriteOutcome::AlreadyPresent,
|
||||
variant_id,
|
||||
ksp_store_api::RawTransactionVariantWriteOutcome::PromotedCompatibleMoreComplete,
|
||||
std::option::Option::Some(promotion),
|
||||
std::option::Option::None,
|
||||
)
|
||||
},
|
||||
ExistingTransactionMatch::ActiveConflict(variant_comparison) => {
|
||||
let variant_id = match persist_or_reuse_native_transaction_variant(&sql_transaction, &raw_transaction, linked_at).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
(ksp_store_api::RawEntityWriteOutcome::AlreadyPresent, variant_id, std::option::Option::Some(promotion))
|
||||
let conflict_transition = match open_or_update_raw_transaction_conflict(
|
||||
&sql_transaction,
|
||||
raw_transaction.reference(),
|
||||
canonical_variant_id,
|
||||
variant_id,
|
||||
variant_comparison,
|
||||
linked_at,
|
||||
)
|
||||
.await
|
||||
{
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
log_raw_transaction_content_conflict_provenance(&sql_transaction, network, &observation).await;
|
||||
(
|
||||
ksp_store_api::RawEntityWriteOutcome::AlreadyPresent,
|
||||
variant_id,
|
||||
ksp_store_api::RawTransactionVariantWriteOutcome::QuarantinedConflict,
|
||||
std::option::Option::None,
|
||||
std::option::Option::Some(conflict_transition),
|
||||
)
|
||||
},
|
||||
ExistingTransactionMatch::Purged => {
|
||||
if mode == ksp_store_api::RawTransactionAcquisitionMode::ForceRehydrate {
|
||||
@@ -748,15 +795,22 @@ pub(crate) async fn persist_raw_transaction_acquisition(
|
||||
if let std::result::Result::Err(error) = variant_result {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
(ksp_store_api::RawEntityWriteOutcome::Rehydrated, canonical_variant_id, std::option::Option::None)
|
||||
(
|
||||
ksp_store_api::RawEntityWriteOutcome::Rehydrated,
|
||||
canonical_variant_id,
|
||||
ksp_store_api::RawTransactionVariantWriteOutcome::Rehydrated,
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
)
|
||||
} else {
|
||||
let commit_result = sql_transaction.commit().await;
|
||||
if commit_result.is_err() {
|
||||
return std::result::Result::Err(write_failed("raw_acquisition_commit"));
|
||||
}
|
||||
return std::result::Result::Ok(ksp_store_api::RawAcquisitionWriteOutcome::new(
|
||||
return std::result::Result::Ok(ksp_store_api::RawAcquisitionWriteOutcome::with_transaction_variant(
|
||||
ksp_store_api::RawEntityWriteOutcome::SkippedPurged,
|
||||
ksp_store_api::RawObservationWriteOutcome::NotRecorded,
|
||||
ksp_store_api::RawTransactionVariantWriteOutcome::SkippedPurged,
|
||||
));
|
||||
}
|
||||
},
|
||||
@@ -778,7 +832,18 @@ pub(crate) async fn persist_raw_transaction_acquisition(
|
||||
if let std::option::Option::Some(transition) = canonical_promotion {
|
||||
log_raw_transaction_canonical_promotion_committed(network, raw_transaction.slot(), transition);
|
||||
}
|
||||
return std::result::Result::Ok(ksp_store_api::RawAcquisitionWriteOutcome::new(entity_outcome, observation_outcome));
|
||||
if let std::option::Option::Some(transition) = quarantined_conflict {
|
||||
let stored = decode_raw_transaction_row(network, locked.clone());
|
||||
if let std::result::Result::Ok(std::option::Option::Some(stored)) = stored {
|
||||
log_raw_transaction_content_conflict(network, &stored, &raw_transaction);
|
||||
}
|
||||
log_raw_transaction_conflict_quarantined_committed(network, raw_transaction.slot(), transition);
|
||||
}
|
||||
return std::result::Result::Ok(ksp_store_api::RawAcquisitionWriteOutcome::with_transaction_variant(
|
||||
entity_outcome,
|
||||
observation_outcome,
|
||||
transaction_variant_outcome,
|
||||
));
|
||||
}
|
||||
|
||||
/// Persists one additional observation for an already known RAW transaction.
|
||||
@@ -922,11 +987,21 @@ struct RawCanonicalPromotionTransition {
|
||||
to_variant_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
struct RawTransactionConflictTransition {
|
||||
canonical_variant_id: u64,
|
||||
incoming_variant_id: u64,
|
||||
reason: ksp_store_api::RawTransactionVariantRelationReason,
|
||||
relation: ksp_store_api::RawTransactionVariantRelation,
|
||||
revision: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum ExistingTransactionMatch {
|
||||
Active,
|
||||
ActiveCompatibleLessComplete,
|
||||
ActiveCompatibleMoreComplete,
|
||||
ActiveConflict(ksp_store_api::RawTransactionVariantComparison),
|
||||
Purged,
|
||||
}
|
||||
|
||||
@@ -1259,6 +1334,155 @@ async fn persist_or_reuse_native_transaction_variant(
|
||||
};
|
||||
}
|
||||
|
||||
async fn open_or_update_raw_transaction_conflict(
|
||||
sql_transaction: &deadpool_postgres::Transaction<'_>,
|
||||
reference: &ksp_store_api::RawTransactionReference,
|
||||
canonical_variant_id: u64,
|
||||
incoming_variant_id: u64,
|
||||
comparison: ksp_store_api::RawTransactionVariantComparison,
|
||||
observed_at_unix_millis: i64,
|
||||
) -> std::result::Result<RawTransactionConflictTransition, crate::PostgresBackendError> {
|
||||
if canonical_variant_id == incoming_variant_id {
|
||||
return std::result::Result::Err(data_invalid("raw_conflict_variant_identity"));
|
||||
}
|
||||
if !matches!(comparison.relation(), ksp_store_api::RawTransactionVariantRelation::Conflict | ksp_store_api::RawTransactionVariantRelation::Incomparable) {
|
||||
return std::result::Result::Err(data_invalid("raw_conflict_relation"));
|
||||
}
|
||||
let signature = reference.signature();
|
||||
let signature_bytes: &[u8] = signature.as_bytes();
|
||||
let relation_code = comparison.relation().code();
|
||||
let reason_code = comparison.reason().code();
|
||||
let row_result = sql_transaction.query_opt(LOCK_TRANSACTION_CONFLICT_SQL, &[&signature_bytes]).await;
|
||||
let row = match row_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(write_failed("raw_conflict_lock")),
|
||||
};
|
||||
let canonical_variant_id_text = canonical_variant_id.to_string();
|
||||
let incoming_variant_id_text = incoming_variant_id.to_string();
|
||||
if row.is_none() {
|
||||
let insert_result = sql_transaction
|
||||
.execute(
|
||||
INSERT_TRANSACTION_CONFLICT_SQL,
|
||||
&[
|
||||
&signature_bytes,
|
||||
&canonical_variant_id_text.as_str(),
|
||||
&incoming_variant_id_text.as_str(),
|
||||
&relation_code,
|
||||
&reason_code,
|
||||
&observed_at_unix_millis,
|
||||
],
|
||||
)
|
||||
.await;
|
||||
return match insert_result {
|
||||
std::result::Result::Ok(1) => std::result::Result::Ok(RawTransactionConflictTransition {
|
||||
canonical_variant_id,
|
||||
incoming_variant_id,
|
||||
reason: comparison.reason(),
|
||||
relation: comparison.relation(),
|
||||
revision: 1,
|
||||
}),
|
||||
std::result::Result::Ok(_) => std::result::Result::Err(data_invalid("raw_conflict_insert_count")),
|
||||
std::result::Result::Err(_) => std::result::Result::Err(write_failed("raw_conflict_insert")),
|
||||
};
|
||||
}
|
||||
let row = match row {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return std::result::Result::Err(data_invalid("raw_conflict_lock_state")),
|
||||
};
|
||||
let status = match row.try_get::<_, std::string::String>("status") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(data_invalid("raw_conflict_status")),
|
||||
};
|
||||
if status != ksp_store_api::RawTransactionConflictStatus::Open.code() && status != ksp_store_api::RawTransactionConflictStatus::Resolved.code() {
|
||||
return std::result::Result::Err(data_invalid("raw_conflict_status"));
|
||||
}
|
||||
let revision_text = match row.try_get::<_, std::string::String>("revision_text") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(data_invalid("raw_conflict_revision")),
|
||||
};
|
||||
let revision = match decode_u64_decimal(revision_text.as_str(), "raw_conflict_revision") {
|
||||
std::result::Result::Ok(value) if value > 0 => value,
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(data_invalid("raw_conflict_revision")),
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let existing_canonical_text = match row.try_get::<_, std::string::String>("canonical_variant_id_text") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(data_invalid("raw_conflict_canonical_variant_id")),
|
||||
};
|
||||
let existing_canonical = match decode_u64_decimal(existing_canonical_text.as_str(), "raw_conflict_canonical_variant_id") {
|
||||
std::result::Result::Ok(value) if value > 0 => value,
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(data_invalid("raw_conflict_canonical_variant_id")),
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let existing_incoming_text = match row.try_get::<_, std::string::String>("incoming_variant_id_text") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(data_invalid("raw_conflict_incoming_variant_id")),
|
||||
};
|
||||
let existing_incoming = match decode_u64_decimal(existing_incoming_text.as_str(), "raw_conflict_incoming_variant_id") {
|
||||
std::result::Result::Ok(value) if value > 0 => value,
|
||||
std::result::Result::Ok(_) => return std::result::Result::Err(data_invalid("raw_conflict_incoming_variant_id")),
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let existing_relation = match row.try_get::<_, std::string::String>("latest_relation") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(data_invalid("raw_conflict_relation")),
|
||||
};
|
||||
let existing_reason = match row.try_get::<_, std::string::String>("latest_reason_code") {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(data_invalid("raw_conflict_reason")),
|
||||
};
|
||||
if status == ksp_store_api::RawTransactionConflictStatus::Open.code()
|
||||
&& existing_canonical == canonical_variant_id
|
||||
&& existing_incoming == incoming_variant_id
|
||||
&& existing_relation == relation_code
|
||||
&& existing_reason == reason_code
|
||||
{
|
||||
return std::result::Result::Ok(RawTransactionConflictTransition {
|
||||
canonical_variant_id,
|
||||
incoming_variant_id,
|
||||
reason: comparison.reason(),
|
||||
relation: comparison.relation(),
|
||||
revision,
|
||||
});
|
||||
}
|
||||
let updated_at = match row.try_get::<_, i64>("updated_at_unix_millis") {
|
||||
std::result::Result::Ok(value) => std::cmp::max(value, observed_at_unix_millis),
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(data_invalid("raw_conflict_updated_at")),
|
||||
};
|
||||
let next_revision = match revision.checked_add(1) {
|
||||
std::option::Option::Some(value) if value != 0 => value,
|
||||
_ => return std::result::Result::Err(data_invalid("raw_conflict_revision_exhausted")),
|
||||
};
|
||||
let next_revision_text = next_revision.to_string();
|
||||
let update_result = sql_transaction
|
||||
.execute(
|
||||
UPDATE_TRANSACTION_CONFLICT_SQL,
|
||||
&[
|
||||
&signature_bytes,
|
||||
&next_revision_text.as_str(),
|
||||
&canonical_variant_id_text.as_str(),
|
||||
&incoming_variant_id_text.as_str(),
|
||||
&relation_code,
|
||||
&reason_code,
|
||||
&updated_at,
|
||||
&revision_text.as_str(),
|
||||
],
|
||||
)
|
||||
.await;
|
||||
return match update_result {
|
||||
std::result::Result::Ok(1) => std::result::Result::Ok(RawTransactionConflictTransition {
|
||||
canonical_variant_id,
|
||||
incoming_variant_id,
|
||||
reason: comparison.reason(),
|
||||
relation: comparison.relation(),
|
||||
revision: next_revision,
|
||||
}),
|
||||
std::result::Result::Ok(0) => std::result::Result::Err(data_invalid("raw_conflict_stale_revision")),
|
||||
std::result::Result::Ok(_) => std::result::Result::Err(data_invalid("raw_conflict_update_count")),
|
||||
std::result::Result::Err(_) => std::result::Result::Err(write_failed("raw_conflict_update")),
|
||||
};
|
||||
}
|
||||
|
||||
async fn promote_more_complete_transaction_variant(
|
||||
sql_transaction: &deadpool_postgres::Transaction<'_>,
|
||||
locked: &RawTransactionDbRow,
|
||||
@@ -1657,8 +1881,7 @@ fn compare_existing_transaction(
|
||||
},
|
||||
ksp_store_api::RawTransactionVariantRelation::CompatibleMoreComplete => std::result::Result::Ok(ExistingTransactionMatch::ActiveCompatibleMoreComplete),
|
||||
ksp_store_api::RawTransactionVariantRelation::Conflict | ksp_store_api::RawTransactionVariantRelation::Incomparable => {
|
||||
log_raw_transaction_content_conflict(network, &stored, incoming);
|
||||
std::result::Result::Err(conflict("raw_acquisition_content_conflict"))
|
||||
std::result::Result::Ok(ExistingTransactionMatch::ActiveConflict(comparison))
|
||||
},
|
||||
_ => std::result::Result::Err(data_invalid("raw_acquisition_variant_relation")),
|
||||
};
|
||||
@@ -1925,6 +2148,22 @@ fn log_raw_transaction_canonical_promotion_committed(network: &ksp_store_api::Ra
|
||||
return;
|
||||
}
|
||||
|
||||
fn log_raw_transaction_conflict_quarantined_committed(network: &ksp_store_api::RawNetworkId, slot: u64, transition: RawTransactionConflictTransition) {
|
||||
ksp_logging_lib::warn!(
|
||||
target: crate::TRACING_TARGET,
|
||||
domain = "store.raw_transaction.quarantined_conflict",
|
||||
network = network.as_str(),
|
||||
slot = slot,
|
||||
canonical_variant_id = transition.canonical_variant_id,
|
||||
incoming_variant_id = transition.incoming_variant_id,
|
||||
conflict_revision = transition.revision,
|
||||
relation = transition.relation.code(),
|
||||
reason = transition.reason.code(),
|
||||
"PostgreSQL Store committed a durable RAW transaction conflict case"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
fn log_raw_transaction_content_conflict(
|
||||
network: &ksp_store_api::RawNetworkId,
|
||||
stored: &ksp_store_api::RawTransaction,
|
||||
@@ -1964,7 +2203,7 @@ fn log_raw_transaction_content_conflict(
|
||||
incoming_log_messages_prefix_of_stored = diagnostic.log_messages.incoming_prefix_of_stored,
|
||||
stored_log_messages_has_truncation_marker = diagnostic.log_messages.stored_has_truncation_marker,
|
||||
incoming_log_messages_has_truncation_marker = diagnostic.log_messages.incoming_has_truncation_marker,
|
||||
"PostgreSQL Store rejected divergent canonical RAW transaction"
|
||||
"PostgreSQL Store classified divergent canonical RAW transaction content"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user