Lifetime issues when porting sync closure to async closure in Rust - redis
I'm currently trying to port some Rust code that uses the Redis crate and Redis transactions from sync to async code, and am having some issues (currently lifetime-related, but the root cause might lie elsewhere in the port).
The code in both cases uses the following dependencies in Cargo.toml:
[dependencies]
redis = "0.16"
tokio = { version = "0.2", features = ["full"] }
A minimal example of working synchronous code looks as follows:
use redis::{pipe, cmd, Pipeline, ToRedisArgs, RedisResult};
fn main() -> RedisResult<()> {
let client = redis::Client::open("redis://127.0.0.1/").unwrap();
let mut sync_conn = client.get_connection()?;
let key = "foo";
let (val,): (u32,) = transaction(&mut sync_conn, &[key], |conn, pipe| {
pipe.set(key, 1)
.ignore()
.get(key)
.query(conn)
})?;
println!("val: {}", val);
Ok(())
}
fn transaction<
C: redis::ConnectionLike,
K: ToRedisArgs,
T,
F: FnMut(&mut C, &mut Pipeline) -> RedisResult<Option<T>>,
>(
con: &mut C,
keys: &[K],
func: F,
) -> RedisResult<T> {
let mut func = func;
loop {
cmd("WATCH").arg(keys).query(con)?;
if let Some(response) = func(con, pipe().atomic())? {
cmd("UNWATCH").query(con)?;
return Ok(response);
}
}
}
My attempt to convert this to async code looks like:
use redis::{AsyncCommands, pipe, cmd, Pipeline, ToRedisArgs, RedisResult, aio::ConnectionLike};
use std::future::Future;
#[tokio::main]
async fn main() -> RedisResult<()> {
let client = redis::Client::open("redis://127.0.0.1/").unwrap();
let mut async_conn = client.get_async_connection().await?;
let key = "foo";
let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
pipe.set(key, 1)
.ignore()
.get(key)
.query_async(conn).await
}).await?;
println!("val: {}", val);
Ok(())
}
pub async fn async_transaction<
C: ConnectionLike + Send,
K: ToRedisArgs,
T,
F: FnMut(&mut C, &mut Pipeline) -> Fut,
Fut: Future<Output = RedisResult<Option<T>>>,
>(
con: & mut C,
keys: &[K],
func: F,
) -> RedisResult<T> {
let mut func = func;
loop {
cmd("WATCH").arg(keys).query_async(con).await?;
if let Some(response) = func(con, pipe().atomic()).await? {
cmd("UNWATCH").query_async(con).await?;
return Ok(response);
}
}
}
The main changes were to use an async connection, to use async/await and query_async instead of query. The other major change was for the function passed to async_transaction to return a Future instead of the result directly.
Trying to compile this however results in 19 errors however (they mostly appear to be lifetime based):
error[E0486]: type of expression contains references that are not valid during the expression: `for<'_, '_> fn(&mut redis::aio::Connection, &[&str], [closure#src/main.rs:11:69: 16:6 key:&&str]) -> impl std::future::Future {async_transaction::<redis::aio::Connection, &str, (u32,), [closure#src/main.rs:11:69: 16:6 key:&&str], impl std::future::Future>}`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| ^^^^^^^^^^^^^^^^^
|
note: type is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `for<'_, '_> fn(&mut redis::aio::Connection, &[&str], [closure#src/main.rs:11:69: 16:6 key:&&str]) -> impl std::future::Future {async_transaction::<redis::aio::Connection, &str, (u32,), [closure#src/main.rs:11:69: 16:6 key:&&str], impl std::future::Future>}`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| ^^^^^^^^^^^^^^^^^
|
note: type is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `impl std::future::Future`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |______^
|
note: type is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `impl std::future::Future`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |______^
|
note: type is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `impl std::future::Future`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `impl std::future::Future`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `&mut impl std::future::Future`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `&mut impl std::future::Future`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `unsafe fn(&mut impl std::future::Future) -> std::pin::Pin<&mut impl std::future::Future> {std::pin::Pin::<&mut impl std::future::Future>::new_unchecked}`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `unsafe fn(&mut impl std::future::Future) -> std::pin::Pin<&mut impl std::future::Future> {std::pin::Pin::<&mut impl std::future::Future>::new_unchecked}`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `std::pin::Pin<&mut impl std::future::Future>`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `std::pin::Pin<&mut impl std::future::Future>`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `for<'r, 's, 't0> fn(std::pin::Pin<&'r mut impl std::future::Future>, &'s mut std::task::Context<'t0>) -> std::task::Poll<<impl std::future::Future as std::future::Future>::Output> {<impl std::future::Future as std::future::Future>::poll}`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0486]: type of expression contains references that are not valid during the expression: `for<'r, 's, 't0> fn(std::pin::Pin<&'r mut impl std::future::Future>, &'s mut std::task::Context<'t0>) -> std::task::Poll<<impl std::future::Future as std::future::Future>::Output> {<impl std::future::Future as std::future::Future>::poll}`
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: type is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0481]: lifetime of function argument does not outlive the function call
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: the function argument is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0481]: lifetime of function argument does not outlive the function call
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: the function argument is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0488]: lifetime of variable does not enclose its declaration
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: the variable is only valid for the anonymous lifetime #2 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0488]: lifetime of variable does not enclose its declaration
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: the variable is only valid for the anonymous lifetime #3 defined on the body at 11:69
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the body at 11:69...
--> src/main.rs:11:69
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| _____________________________________________________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |_____^
note: ...so that the type `impl std::future::Future` is not borrowed for too long
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
note: but, the lifetime must be valid for the call at 11:26...
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
note: ...so that argument is valid for the call
--> src/main.rs:11:26
|
11 | let (val,): (u32,) = async_transaction(&mut async_conn, &[key], |conn, pipe| async {
| __________________________^
12 | | pipe.set(key, 1)
13 | | .ignore()
14 | | .get(key)
15 | | .query_async(conn).await
16 | | }).await?;
| |____________^
error: aborting due to 19 previous errors
For more information about this error, try `rustc --explain E0495`.
error: could not compile `redistest`.
To learn more, run the command again with --verbose.
Are there some lifetime annotations I can apply to fix this, or should I instead be doing something else to move from sync to async code in this case?
Related
animated flatlist with animated ref typescript error
Why I get this ts error ? (property) ref: React.RefObject<FlatList<any>> Type '{ ref: RefObject<FlatList<any>>; data: IInstructionsData[]; renderItem: ListRenderItem<IInstructionsData>; ... 6 more ...; showsHorizontalScrollIndicator: false; }' is not assignable to type 'IntrinsicAttributes & { ItemSeparatorComponent?: ComponentType<any> | AnimatedNode<ComponentType<any> | null | undefined> | null | undefined; ... 146 more ...; simultaneousHandlers?: Ref<...> | ... 2 more ... | undefined; } & { ...; } & { ...; }'. Property 'ref' does not exist on type 'IntrinsicAttributes & { ItemSeparatorComponent?: ComponentType<any> | AnimatedNode<ComponentType<any> | null | undefined> | null | undefined; ... 146 more ...; simultaneousHandlers?: Ref<...> | ... 2 more ... | undefined; } & { ...; } & { ...; }'.ts(2322) Code: import Animated, { useAnimatedScrollHandler, useSharedValue, useDerivedValue, useAnimatedRef } from 'react-native-reanimated'; const AnimatedFlatlist = (Animated.createAnimatedComponent( FlatList ) as unknown) as <T>(props: RNGHFlatListProps<T>) => React.ReactElement; <AnimatedFlatlist ref={flatlistRef} data={mockData} renderItem={renderItem} onScroll={handleScroll} keyExtractor={(item, i) => i.toString()} initialNumToRender={2} keyboardShouldPersistTaps='handled' horizontal pagingEnabled showsHorizontalScrollIndicator={false} /> the error comes at AnimatedFlatlist on ref what I am doing wrong and how can I solve this issue ?
Your code snippet is incomplete. Where did you define the ref for the AnimatedFlatList? It should look something like this: const flatListRef = useRef<FlatList<T>>(null);
Laravel Eloquent - Return unique values only and ignore all that appear more than once
I have 2 database tables. |---------------------|------------------| | Users | Matches | |---------------------|------------------| | user_id | match_id | |---------------------|------------------| | user_1 | |------------------| | user_2 | |------------------| with user_1 and user_2 being user_ids. I am now trying to retrieve all matches with unique values only. As soon as a user ID is used twice, I don't want to retrieve ANY matches containing the id. Example: MATCHES (match_id, user_1, user_2): 1, 1, 2 2, 1, 3 3, 4, 5 4, 6, 7 5, 7, 8 The query should return 3, 4, 5 ONLY, because it's the only match containing only unique user_ids. How should I go about this? I've been trying an approach using ->distinct() but that doesn't work since it only removes duplicates but I want to kick other entries containing the values as well.
Simple and crude, not a query based solution, but will get you what you want. public function strictlyUniqueMatches() { $matches = Matches::distinct()->get(); $present = []; foreach ($matches as $idx => $match) { if (!isset($present[$match->user_1])) { $present[$match->user_1] = 0; } if (!isset($present[$match->user_2])) { $present[$match->user_2] = 0; } $present[$match->user_1]++; $present[$match->user_2]++; } return $matches->filter(function ($match) use ($present) { if ($present[$match->user_1] > 1) { return false; } if ($present[$match->user_2] > 1) { return false; } return true; }); }
Side-effects-in-computed-properties
I want to avoid having side effects in my code, but I don't know how to fix these, does some one can help? computed: { sumarVerduras(){ this.totalVerduras = 0; for( const verdura of this.verduras){ this.totalVerduras = this.totalVerduras + verdura.cantidad } return this.totalVerduras; } } It work as I want but side effect is there Module Warning (from ./node_modules/eslint-loader/index.js): error: Unexpected side effect in "sumarVerduras" computed property (vue/no-side-effects-in-computed-properties) at src\App.vue:53:7: 51 | computed: { 52 | sumarVerduras(){ 53 | this.totalVerduras = 0; | ^ 54 | for( const verdura of this.verduras){ 55 | this.totalVerduras = this.totalVerduras + verdura.cantidad 56 | } return this.totalVerduras; error: Unexpected side effect in "sumarVerduras" computed property (vue/no-side-effects-in-computed-properties) at src\App.vue:55:11: 53 | this.totalVerduras = 0; 54 | for( const verdura of this.verduras){ 55 | this.totalVerduras = this.totalVerduras + verdura.cantidad | ^ 56 | } return this.totalVerduras; 57 | } 58 | }
You should not edit any Vue component's data in computed property. Here you modify this.totalVerduras, which is considered as Vue's component data. You can change to: computed: { sumarVerduras() { let totalVerduras = 0; for (const verdura of this.verduras) { totalVerduras = totalVerduras + verdura.cantidad } return totalVerduras; } }
You can do this as well: computed: { sumarVerduras() { return verduras.reduce((a, x) => a + x.cantidad, 0); } } This method gets rid of totalVerduras variable and the for loop.
How to return nested JSON?
I have 3 table in PostgreSQL database. QUESTIONS table: | id (int) | text (text) | |----------|--------------------------------------| | 1 | What is your favorite color? | | 2 | What is your favorite football club? | OPTIONS table: | id (int) | text (text) | |----------|-------------| | 1 | red | | 2 | blue | | 3 | grey | | 4 | green | | 5 | brown | QUESTIONS_OPTIONS table: | question_id (int) | option_id (int) | |-------------------|-----------------| | 1 | 1 | | 1 | 2 | | 1 | 3 | | 1 | 4 | | 1 | 5 | In Golang application I create such models: type Option struct { ID int `json:"option_id"` Text string `json:"option_text"` } type Question struct { ID int `json:"question_id"` Text string `json:"question_text"` Options []Option `json:"options"` } In controller I have such code: var GetQuestions = func(responseWriter http.ResponseWriter, request *http.Request) { rows, _ := database.DBSQL.Query("SELECT * FROM questions;") defer rows.Close() var questions []Question for rows.Next() { var question Question var options []Option queries, _ := database.DBSQL.Query(`select options.id as option_id, options.text as option_text from questions_options inner join questions on questions_options.question_id = ` + &question.ID + ` inner join options on questions_options.option_id = options.id`) queries.Close() for queries.Next() { var option Option if err := queries.Scan(&option.ID, &option.Text); err != nil { log.Println(err) } options = append(options, option) } if err := rows.Scan(&question.ID, &question.Text, options); err != nil { // service raise error in this line: sql: expected 2 destination arguments in Scan, not 3 log.Println(err) } questions = append(questions, question) } utils.Response(responseWriter, http.StatusOK, questions) } When I try to make GET request to take all questions with all there options service such incorrect result: [ { "question_id": 0, "question_text": "", "options": null }, { "question_id": 0, "question_text": "", "options": null } ] Where I make mistake?
You should move queries.Close() to the end of loop, like this: var GetQuestions = func(responseWriter http.ResponseWriter, request *http.Request) { rows, _ := database.DBSQL.Query("SELECT * FROM questions;") defer rows.Close() var questions []Question for rows.Next() { var question Question if err := rows.Scan(&question.ID, &question.Text); err != nil { log.Println(err) continue } queries, _ := database.DBSQL.Query(`select options.id as option_id, options.text as option_text from questions_options inner join questions on questions_options.question_id = $1 inner join options on questions_options.option_id = options.id`, question.ID) for queries.Next() { var option Option if err := queries.Scan(&option.ID, &option.Text); err != nil { log.Println(err) } question.Options = append(question.Options, option) } queries.Close() questions = append(questions, question) } utils.Response(responseWriter, http.StatusOK, questions) }
Azure Stream Analytics Pivoting Rows To Columns
I have a data like; [ {"deviceid":"d1","parameter"="p1" value="1" timestamp="2018-03-22T12:33:00"}, {"deviceid":"d1","parameter"="p2" value="2" timestamp="2018-03-22T12:34:00"}, {"deviceid":"d1","parameter"="p2" value="3" timestamp="2018-03-22T12:35:00"}, {"deviceid":"d2","parameter"="p1" value="4" timestamp="2018-03-22T12:36:00"}, {"deviceid":"d2","parameter"="p2" value="5" timestamp="2018-03-22T12:37:00"}, {"deviceid":"d2","parameter"="p2" value="6" timestamp="2018-03-22T12:38:00"}, {"deviceid":"d2","parameter"="p1" value="7" timestamp="2018-03-22T12:43:00"}, {"deviceid":"d2","parameter"="p1" value="8" timestamp="2018-03-22T12:44:00"}, {"deviceid":"d2","parameter"="p2" value="9" timestamp="2018-03-22T12:45:00"}, {"deviceid":"d1","parameter"="p1" value="10" timestamp="2018-03-22T12:46:00"}, {"deviceid":"d1","parameter"="p1" value="11" timestamp="2018-03-22T12:47:00"}, {"deviceid":"d1","parameter"="p2" value="12" timestamp="2018-03-22T12:49:00"} ] I want to pivot that parameter values(for every 10 minutes window) and display last recieved value of each parameter for each deviceid and like this edit*(Parameters will be dynamic not just p1 and p2); ------------------------------------------------------------ | deviceid| windowtime | p1 | p2 | ------------------------------------------------------------ | d1 | 2018-03-22 12:40 | 1 | 3 | ------------------------------------------------------------ | d2 | 2018-03-22 12:40 | 4 | 6 | ------------------------------------------------------------ | d2 | 2018-03-22 12:50 | 8 | 9 | ------------------------------------------------------------ | d1 | 2018-03-22 12:50 | 11 | 12 | ------------------------------------------------------------ Thank You.
Another more clear way is to use UDA : SELECT deviceid, system.Timestamp as windowtime, uda.P1UDA(test) AS P1, uda.P2UDA(test) AS P2 FROM test TIMESTAMP BY timestamp GROUP BY deviceid, TumblingWindow(minute, 10) JavaScript UDA: function P1UDA() { this.init = function () { this.state = 0; } this.accumulate = function (value, timestamp) { if (value.parameter == 'p1') { if (value.value > this.state) { this.state = value.value; } } } this.computeResult = function () { return this.state; } } function P2UDA() { this.init = function () { this.state = 0; } this.accumulate = function (value, timestamp) { if (value.parameter == 'p2') { if (value.value > this.state) { this.state = value.value; } } } this.computeResult = function () { return this.state; } }
you can try like below script : with tempone as (SELECT deviceid, system.Timestamp as windowtime, max(value) AS P1 FROM test TIMESTAMP BY timestamp where parameter = 'p1' GROUP BY deviceid, TumblingWindow(minute, 10)), temptwo AS ( SELECT deviceid, system.Timestamp as windowtime, max(value) AS P2 FROM test TIMESTAMP BY timestamp where parameter = 'p2' GROUP BY deviceid, TumblingWindow(minute, 10)) select tempone.deviceid, tempone.windowtime, tempone.P1, temptwo.P2 from tempone join temptwo on tempone.deviceid = temptwo.deviceid and DATEDIFF(minute,tempone, temptwo) BETWEEN 0 AND 1