Skip to content
Merged
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
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/src/subgraph/instance_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ enum BlockProcessingError {
#[error("{0:#}")]
Unknown(Error),

// The error had a determinstic cause but, for a possibly non-deterministic reason, we chose to
// The error had a deterministic cause but, for a possibly non-deterministic reason, we chose to
// halt processing due to the error.
#[error("{0}")]
Deterministic(SubgraphError),
Expand Down
31 changes: 29 additions & 2 deletions graph/src/components/subgraph/host.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::cmp::PartialEq;
use std::fmt;
use std::sync::Arc;
use std::time::Instant;

use anyhow::Error;
use async_trait::async_trait;
Expand Down Expand Up @@ -129,15 +130,41 @@ impl HostMetrics {

pub fn observe_handler_execution_time(&self, duration: f64, handler: &str) {
self.handler_execution_time
.with_label_values(vec![handler].as_slice())
.with_label_values(&[handler][..])
.observe(duration);
}

pub fn observe_host_fn_execution_time(&self, duration: f64, fn_name: &str) {
self.host_fn_execution_time
.with_label_values(vec![fn_name].as_slice())
.with_label_values(&[fn_name][..])
.observe(duration);
}

pub fn time_host_fn_execution_region(
self: Arc<HostMetrics>,
fn_name: &'static str,
) -> HostFnExecutionTimer {
HostFnExecutionTimer {
start: Instant::now(),
metrics: self,
fn_name,
}
}
}

#[must_use]
pub struct HostFnExecutionTimer {
start: Instant,
metrics: Arc<HostMetrics>,
fn_name: &'static str,
}

impl Drop for HostFnExecutionTimer {
fn drop(&mut self) {
let elapsed = (Instant::now() - self.start).as_secs_f64();
self.metrics
.observe_host_fn_execution_time(elapsed, self.fn_name)
}
Comment thread
That3Percent marked this conversation as resolved.
}

pub trait RuntimeHostBuilder: Clone + Send + Sync + 'static {
Expand Down
2 changes: 1 addition & 1 deletion graph/src/data/graphql/shape_hash.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Calculate a hash for a GraphQL query that reflects the shape of
//! the query. The shape hash will be the same for two instancs of a query
//! the query. The shape hash will be the same for two instances of a query
//! that are deemed identical except for unimportant details. Those details
//! are any values used with filters, and any differences in the query
//! name or response keys
Expand Down
44 changes: 26 additions & 18 deletions runtime/derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,29 +67,34 @@ fn asc_type_derive_struct(item_struct: ItemStruct) -> TokenStream {

TokenStream::from(quote! {
impl#impl_generics AscType for #struct_name#ty_generics #where_clause {
fn to_asc_bytes(&self) -> Vec<u8> {
fn to_asc_bytes(&self) -> Result<Vec<u8>, DeterministicHostError> {
let mut bytes = Vec::new();
#(bytes.extend_from_slice(&self.#field_names.to_asc_bytes());)*
#(bytes.extend_from_slice(&self.#field_names.to_asc_bytes()?);)*

// Assert that the struct has no padding.
assert_eq!(bytes.len(), size_of::<Self>());
bytes
Ok(bytes)
}

#[allow(unused_variables)]
fn from_asc_bytes(asc_obj: &[u8]) -> Self {
assert_eq!(asc_obj.len(), size_of::<Self>());
fn from_asc_bytes(asc_obj: &[u8]) -> Result<Self, DeterministicHostError> {
if asc_obj.len() != size_of::<Self>() {
return Err(DeterministicHostError(anyhow::anyhow!("Size does not match")));
}
let mut offset = 0;

#(
let field_size = std::mem::size_of::<#field_types>();
let #field_names2 = AscType::from_asc_bytes(&asc_obj[offset..(offset + field_size)]);
let field_data = asc_obj.get(offset..(offset + field_size)).ok_or_else(|| {
DeterministicHostError(anyhow!("Attempted to read past end of array"))
})?;
let #field_names2 = AscType::from_asc_bytes(&field_data)?;
offset += field_size;
)*

Self {
Ok(Self {
#(#field_names3,)*
}
})
}
}
})
Expand All @@ -109,7 +114,7 @@ fn asc_type_derive_struct(item_struct: ItemStruct) -> TokenStream {
//
// Example output:
// impl AscType for JsonValueKind {
// fn to_asc_bytes(&self) -> Vec<u8> {
// fn to_asc_bytes(&self) -> Result<Vec<u8>, DeterministicHostError> {
// let discriminant: u32 = match *self {
// JsonValueKind::Null => 0u32,
// JsonValueKind::Bool => 1u32,
Expand All @@ -118,11 +123,14 @@ fn asc_type_derive_struct(item_struct: ItemStruct) -> TokenStream {
// JsonValueKind::Array => 4u32,
// JsonValueKind::Object => 5u32,
// };
// discriminant.to_asc_bytes()
// Ok(discriminant.to_asc_bytes())
// }
//
// fn from_asc_bytes(asc_obj: &[u8]) -> Self {
// fn from_asc_bytes(asc_obj: &[u8]) -> Result<Self, DeterministicHostError> {
// let mut u32_bytes: [u8; size_of::<u32>()] = [0; size_of::<u32>()];
// if std::mem::size_of_val(&u32_bytes) != std::mem::size_of_val(&as_obj) {
// return Err(DeterministicHostError(anyhow::anyhow!("Invalid asc bytes size")));
// }
// u32_bytes.copy_from_slice(&asc_obj);
// let discr = u32::from_le_bytes(u32_bytes);
// match discr {
Expand All @@ -132,7 +140,7 @@ fn asc_type_derive_struct(item_struct: ItemStruct) -> TokenStream {
// 3u32 => JsonValueKind::String,
// 4u32 => JsonValueKind::Array,
// 5u32 => JsonValueKind::Object,
// _ => panic!("value {} is out of range for {}", discr, "JsonValueKind"),
// _ => Err(DeterministicHostError(anyhow::anyhow!("value {} is out of range for {}", discr, "JsonValueKind")),
// }
// }
// }
Expand All @@ -155,20 +163,20 @@ fn asc_type_derive_enum(item_enum: ItemEnum) -> TokenStream {

TokenStream::from(quote! {
impl#impl_generics AscType for #enum_name#ty_generics #where_clause {
fn to_asc_bytes(&self) -> Vec<u8> {
fn to_asc_bytes(&self) -> Result<Vec<u8>, DeterministicHostError> {
let discriminant: u32 = match *self {
#(#enum_name_iter::#variant_paths => #variant_discriminant,)*
};
discriminant.to_asc_bytes()
}

fn from_asc_bytes(asc_obj: &[u8]) -> Self {
let mut u32_bytes: [u8; size_of::<u32>()] = [0; size_of::<u32>()];
u32_bytes.copy_from_slice(&asc_obj);
fn from_asc_bytes(asc_obj: &[u8]) -> Result<Self, DeterministicHostError> {
let u32_bytes = ::std::convert::TryFrom::try_from(asc_obj)
.map_err(|_| DeterministicHostError(anyhow::anyhow!("Invalid asc bytes size")))?;
let discr = u32::from_le_bytes(u32_bytes);
match discr {
#(#variant_discriminant2 => #enum_name_iter2::#variant_paths2,)*
_ => panic!("value {} is out of range for {}", discr, stringify!(#enum_name))
#(#variant_discriminant2 => Ok(#enum_name_iter2::#variant_paths2),)*
_ => Err(DeterministicHostError(anyhow::anyhow!("value {} is out of range for {}", discr, stringify!(#enum_name))))
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions runtime/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ strum = "0.20.0"
strum_macros = "0.20.1"
bytes = "0.5"
anyhow = "1.0"

wasmtime = "0.21.0"

defer = "0.1"
never = "0.1"

[dev-dependencies]
graphql-parser = "0.3"
Expand Down
41 changes: 27 additions & 14 deletions runtime/wasm/src/asc_abi/asc_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::error::DeterministicHostError;

use super::{class::EnumPayload, AscHeap, AscType, AscValue};
use std::fmt;
use std::marker::PhantomData;
Expand Down Expand Up @@ -31,31 +33,41 @@ impl<C> AscPtr<C> {
pub(crate) fn wasm_ptr(self) -> u32 {
self.0
}
#[inline(always)]
pub fn new(heap_ptr: u32) -> Self {
Self(heap_ptr, PhantomData)
}
}

impl<C: AscType> AscPtr<C> {
/// Create a pointer that is equivalent to AssemblyScript's `null`.
#[inline(always)]
pub(crate) fn null() -> Self {
AscPtr(0, PhantomData)
AscPtr::new(0)
}

/// Read from `self` into the Rust struct `C`.
pub(super) fn read_ptr<H: AscHeap>(self, heap: &H) -> C {
C::from_asc_bytes(&heap.get(self.0, C::asc_size(self, heap)))
pub(super) fn read_ptr<H: AscHeap>(self, heap: &H) -> Result<C, DeterministicHostError> {
let bytes = heap.get(self.0, C::asc_size(self, heap)?)?;
C::from_asc_bytes(&bytes)
}

/// Allocate `asc_obj` as an Asc object of class `C`.
pub(super) fn alloc_obj<H: AscHeap>(asc_obj: &C, heap: &mut H) -> AscPtr<C> {
AscPtr(heap.raw_new(&asc_obj.to_asc_bytes()), PhantomData)
pub(super) fn alloc_obj<H: AscHeap>(
asc_obj: &C,
heap: &mut H,
) -> Result<AscPtr<C>, DeterministicHostError> {
let heap_ptr = heap.raw_new(&asc_obj.to_asc_bytes()?)?;
Ok(AscPtr::new(heap_ptr))
}

/// Helper used by arrays and strings to read their length.
pub(super) fn read_u32<H: AscHeap>(&self, heap: &H) -> u32 {
pub(super) fn read_u32<H: AscHeap>(&self, heap: &H) -> Result<u32, DeterministicHostError> {
// Read the bytes pointed to by `self` as the bytes of a `u32`.
let raw_bytes = heap.get(self.0, size_of::<u32>() as u32);
let raw_bytes = heap.get(self.0, size_of::<u32>() as u32)?;
let mut u32_bytes: [u8; size_of::<u32>()] = [0; size_of::<u32>()];
u32_bytes.copy_from_slice(&raw_bytes);
u32::from_le_bytes(u32_bytes)
Ok(u32::from_le_bytes(u32_bytes))
}

/// Conversion to `u64` for use with `AscEnum`.
Expand All @@ -70,19 +82,19 @@ impl<C: AscType> AscPtr<C> {

// Erase type information.
pub(crate) fn erase(self) -> AscPtr<()> {
AscPtr(self.0, PhantomData)
AscPtr::new(self.0)
}
}

impl<C> From<u32> for AscPtr<C> {
fn from(ptr: u32) -> Self {
AscPtr(ptr, PhantomData)
AscPtr::new(ptr)
}
}

impl<C> From<EnumPayload> for AscPtr<C> {
fn from(payload: EnumPayload) -> Self {
AscPtr(payload.0 as u32, PhantomData)
AscPtr::new(payload.0 as u32)
}
}

Expand All @@ -93,12 +105,13 @@ impl<C> From<AscPtr<C>> for EnumPayload {
}

impl<T> AscType for AscPtr<T> {
fn to_asc_bytes(&self) -> Vec<u8> {
fn to_asc_bytes(&self) -> Result<Vec<u8>, DeterministicHostError> {
self.0.to_asc_bytes()
}

fn from_asc_bytes(asc_obj: &[u8]) -> Self {
AscPtr(u32::from_asc_bytes(asc_obj), PhantomData)
fn from_asc_bytes(asc_obj: &[u8]) -> Result<Self, DeterministicHostError> {
let bytes = u32::from_asc_bytes(asc_obj)?;
Ok(AscPtr::new(bytes))
}
}

Expand Down
Loading