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