Spanish [RESUELTO] OkHTTPUtils2 - MySQL Bloqueante

trejocode

Member
Licensed User
Longtime User
Hola, tengo un problema es que no alcanzo a comprender del todo como "Bloquear" una petición HTTP por que utilizo Wait For (Resumable).
Miren el caso:

Selecciono mis elementos de mi base de datos local, y luego envío los datos a una API pero no se envían de forma apropiada por que, como es un evento "no bloqueante" sobrescribe los valores "actuales" por el último, les anexo un ejemplo de lo que tengo:

B4X:
Sub FirstStep
    'Get Data from SQLite
    SQL.BeginTransaction
    Try
        Cursor = SQL.ExecQuery("SELECT column1, column1 FROM table WHERE something = 0")
        For i = 0 To Cursor.RowCount -1
            Cursor.Position = i
            Dim Column1 As String = Cursor.GetInt("column1")
            Dim Column2 As String = Cursor.GetInt("column2")
            SendData(Column1, Column2)
        Next
        SQL.TransactionSuccessful
    Catch
        Log(LastException.Message)
    End Try
    SQL.EndTransaction
    
    
End Sub

Sub SendData(Column1 As Int, Column2 As Int)
    
    Dim Data As Map
    Data.Initialize
    Data.Put("data1", Column1)
    Data.Put("data2", Column2)
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize(Data)
    Dim JSONString As String
    JSONString = JSONGenerator.ToString
    HTTP.PostString("http://"&IP&":8081/petition", JSONString)
    HTTP.GetRequest.SetContentType("application/json")
    HTTP.GetRequest.Timeout = 30000
    Wait For (HTTP) JobDone(response As HttpJob)
    If response.Success Then
        Dim Successful As Boolean = response.Success
        ' If the Data are Inserted on the WebService THEN: UPDATE MY SQLite DB
        If Successful Then
            SQL.BeginTransaction
            Try
                SQL.ExecNonQuery2("UPDATE table SET status = 1 WHERE something = ?", Array As Object(Column1))
                SQL.TransactionSuccessful
            Catch
                Log(LastException.Message)
            End Try
            SQL.EndTransaction
        Else
            Log("Nope, ERROR")
        End If
    End If
    HTTP.Release
    
End Sub

Lo que quisiera es buscar la forma de hacer "Bloqueante el HTTP JOB" el evento de envío al API para que todo se inserte de manera apropiada y no inserte sólo el último, o ¿cómo sería la manera de hacer que se envíe los datos de manera apropiada?
 

inakigarm

Well-Known Member
Licensed User
Longtime User
Hola, tengo un problema es que no alcanzo a comprender del todo como "Bloquear" una petición HTTP por que utilizo Wait For (Resumable).
Miren el caso:

Selecciono mis elementos de mi base de datos local, y luego envío los datos a una API pero no se envían de forma apropiada por que, como es un evento "no bloqueante" sobrescribe los valores "actuales" por el último, les anexo un ejemplo de lo que tengo:

B4X:
Sub FirstStep
    'Get Data from SQLite
    SQL.BeginTransaction
    Try
        Cursor = SQL.ExecQuery("SELECT column1, column1 FROM table WHERE something = 0")
        For i = 0 To Cursor.RowCount -1
            Cursor.Position = i
            Dim Column1 As String = Cursor.GetInt("column1")
            Dim Column2 As String = Cursor.GetInt("column2")
            SendData(Column1, Column2)
        Next
        SQL.TransactionSuccessful
    Catch
        Log(LastException.Message)
    End Try
    SQL.EndTransaction
   
   
End Sub

Sub SendData(Column1 As Int, Column2 As Int)
   
    Dim Data As Map
    Data.Initialize
    Data.Put("data1", Column1)
    Data.Put("data2", Column2)
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize(Data)
    Dim JSONString As String
    JSONString = JSONGenerator.ToString
    HTTP.PostString("http://"&IP&":8081/petition", JSONString)
    HTTP.GetRequest.SetContentType("application/json")
    HTTP.GetRequest.Timeout = 30000
    Wait For (HTTP) JobDone(response As HttpJob)
    If response.Success Then
        Dim Successful As Boolean = response.Success
        ' If the Data are Inserted on the WebService THEN: UPDATE MY SQLite DB
        If Successful Then
            SQL.BeginTransaction
            Try
                SQL.ExecNonQuery2("UPDATE table SET status = 1 WHERE something = ?", Array As Object(Column1))
                SQL.TransactionSuccessful
            Catch
                Log(LastException.Message)
            End Try
            SQL.EndTransaction
        Else
            Log("Nope, ERROR")
        End If
    End If
    HTTP.Release
   
End Sub

Lo que quisiera es buscar la forma de hacer "Bloqueante el HTTP JOB" el evento de envío al API para que todo se inserte de manera apropiada y no inserte sólo el último, o ¿cómo sería la manera de hacer que se envíe los datos de manera apropiada?
Hola, primero has de saber que la transaccion no es necesaria con órdenes tipo SELECT.
Segundo, el problema creo que viene porque no has programado Sendata como un Resumable Sub que devuelva un valor, es decir, que devuelva un valor cuando se haya ejecutado el Sub Sendata, para garantizar que cada Loop sólo finaliza cuando se obtenga el valor de retorno de Sendata..
https://www.b4x.com/android/forum/t...hat-return-values-resumablesub.82670/#content
 

JCO

Active Member
Licensed User
Longtime User
Yo tengo un par de rutinas similares. Lo que hago es que el servicio Web envíe el valor del registro que ha recibido.
Entonces lo recupero con el Response.GetString, y el update de la tabla quedaría algo así como:
B4X:
Dim ID as string = Response.GetString
SQL.ExecNonQuery2("UPDATE table SET status = 1 WHERE something = ?", Array As String(ID))
En este caso, da igual el orden en el que los jobs se completen, porque siempre recibes el código (ID) correspondiente
 

rscheel

Well-Known Member
Licensed User
Longtime User
Debes esperar a que SenData finalice antes de seguir el proceso de FirstStep

Mira la pequeña modificación a tu código

B4X:
Sub FirstStep
    'Get Data from SQLite
    SQL.BeginTransaction
    Try
        Cursor = SQL.ExecQuery("SELECT column1, column1 FROM table WHERE something = 0")
        For i = 0 To Cursor.RowCount -1
            Cursor.Position = i
            Dim Column1 As String = Cursor.GetInt("column1")
            Dim Column2 As String = Cursor.GetInt("column2")
            SendData(Column1, Column2)
            Wait For SendData_Complete 'Cuando finaliza SenData sigue el ciclo for
        Next
        SQL.TransactionSuccessful
    Catch
        Log(LastException.Message)
    End Try
    SQL.EndTransaction
 
 
End Sub

Sub SendData(Column1 As Int, Column2 As Int)
 
    Dim Data As Map
    Data.Initialize
    Data.Put("data1", Column1)
    Data.Put("data2", Column2)
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize(Data)
    Dim JSONString As String
    JSONString = JSONGenerator.ToString
    HTTP.PostString("http://"&IP&":8081/petition", JSONString)
    HTTP.GetRequest.SetContentType("application/json")
    HTTP.GetRequest.Timeout = 30000
    Wait For (HTTP) JobDone(response As HttpJob)
    If response.Success Then
        Dim Successful As Boolean = response.Success
        ' If the Data are Inserted on the WebService THEN: UPDATE MY SQLite DB
        If Successful Then
            SQL.BeginTransaction
            Try
                SQL.ExecNonQuery2("UPDATE table SET status = 1 WHERE something = ?", Array As Object(Column1))
                SQL.TransactionSuccessful
            Catch
                Log(LastException.Message)
            End Try
            SQL.EndTransaction
        Else
            Log("Nope, ERROR")
        End If
    End If
    HTTP.Release
    CallSubDelayed(Me, "SendData_Complete") 'SenData a Finalizado
End Sub
 
Last edited:

trejocode

Member
Licensed User
Longtime User
Hola, primero has de saber que la transaccion no es necesaria con órdenes tipo SELECT.
Segundo, el problema creo que viene porque no has programado Sendata como un Resumable Sub que devuelva un valor, es decir, que devuelva un valor cuando se haya ejecutado el Sub Sendata, para garantizar que cada Loop sólo finaliza cuando se obtenga el valor de retorno de Sendata..
https://www.b4x.com/android/forum/t...hat-return-values-resumablesub.82670/#content
Te agradezco por el tiempo, me viene bien esa documentación
 

trejocode

Member
Licensed User
Longtime User
Yo tengo un par de rutinas similares. Lo que hago es que el servicio Web envíe el valor del registro que ha recibido.
Entonces lo recupero con el Response.GetString, y el update de la tabla quedaría algo así como:
B4X:
Dim ID as string = Response.GetString
SQL.ExecNonQuery2("UPDATE table SET status = 1 WHERE something = ?", Array As String(ID))
En este caso, da igual el orden en el que los jobs se completen, porque siempre recibes el código (ID) correspondiente

Esta es una idea excelente, tiene mucho sentido, me servirá en muchas situación, te agradezco la solución
 

trejocode

Member
Licensed User
Longtime User
Debes esperar a que SenData finalice antes de seguir el proceso de FirstStep

Mira la pequeña modificación a tu código

B4X:
Sub FirstStep
    'Get Data from SQLite
    SQL.BeginTransaction
    Try
        Cursor = SQL.ExecQuery("SELECT column1, column1 FROM table WHERE something = 0")
        For i = 0 To Cursor.RowCount -1
            Cursor.Position = i
            Dim Column1 As String = Cursor.GetInt("column1")
            Dim Column2 As String = Cursor.GetInt("column2")
            SendData(Column1, Column2)
            Wait For SendData_Complete 'Cuando finaliza SenData sigue el ciclo for
        Next
        SQL.TransactionSuccessful
    Catch
        Log(LastException.Message)
    End Try
    SQL.EndTransaction
 
 
End Sub

Sub SendData(Column1 As Int, Column2 As Int)
 
    Dim Data As Map
    Data.Initialize
    Data.Put("data1", Column1)
    Data.Put("data2", Column2)
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize(Data)
    Dim JSONString As String
    JSONString = JSONGenerator.ToString
    HTTP.PostString("http://"&IP&":8081/petition", JSONString)
    HTTP.GetRequest.SetContentType("application/json")
    HTTP.GetRequest.Timeout = 30000
    Wait For (HTTP) JobDone(response As HttpJob)
    If response.Success Then
        Dim Successful As Boolean = response.Success
        ' If the Data are Inserted on the WebService THEN: UPDATE MY SQLite DB
        If Successful Then
            SQL.BeginTransaction
            Try
                SQL.ExecNonQuery2("UPDATE table SET status = 1 WHERE something = ?", Array As Object(Column1))
                SQL.TransactionSuccessful
            Catch
                Log(LastException.Message)
            End Try
            SQL.EndTransaction
        Else
            Log("Nope, ERROR")
        End If
    End If
    HTTP.Release
    CallSubDelayed(Me, "SendData_Complete") 'SenData a Finalizado
End Sub

Gracias, no comprendía que puedo hacer dicha operación con el Wait For, ahora comprendo mejor como controlar los eventos, gracias, probaré esta solución, debido a que mi WebService es en Javascript maneja mucha asincronía, este cambio me viene bien.
 

trejocode

Member
Licensed User
Longtime User
Debes esperar a que SenData finalice antes de seguir el proceso de FirstStep

Mira la pequeña modificación a tu código

B4X:
Sub FirstStep
    'Get Data from SQLite
    SQL.BeginTransaction
    Try
        Cursor = SQL.ExecQuery("SELECT column1, column1 FROM table WHERE something = 0")
        For i = 0 To Cursor.RowCount -1
            Cursor.Position = i
            Dim Column1 As String = Cursor.GetInt("column1")
            Dim Column2 As String = Cursor.GetInt("column2")
            SendData(Column1, Column2)
            Wait For SendData_Complete 'Cuando finaliza SenData sigue el ciclo for
        Next
        SQL.TransactionSuccessful
    Catch
        Log(LastException.Message)
    End Try
    SQL.EndTransaction
 
 
End Sub

Sub SendData(Column1 As Int, Column2 As Int)
 
    Dim Data As Map
    Data.Initialize
    Data.Put("data1", Column1)
    Data.Put("data2", Column2)
    Dim JSONGenerator As JSONGenerator
    JSONGenerator.Initialize(Data)
    Dim JSONString As String
    JSONString = JSONGenerator.ToString
    HTTP.PostString("http://"&IP&":8081/petition", JSONString)
    HTTP.GetRequest.SetContentType("application/json")
    HTTP.GetRequest.Timeout = 30000
    Wait For (HTTP) JobDone(response As HttpJob)
    If response.Success Then
        Dim Successful As Boolean = response.Success
        ' If the Data are Inserted on the WebService THEN: UPDATE MY SQLite DB
        If Successful Then
            SQL.BeginTransaction
            Try
                SQL.ExecNonQuery2("UPDATE table SET status = 1 WHERE something = ?", Array As Object(Column1))
                SQL.TransactionSuccessful
            Catch
                Log(LastException.Message)
            End Try
            SQL.EndTransaction
        Else
            Log("Nope, ERROR")
        End If
    End If
    HTTP.Release
    CallSubDelayed(Me, "SendData_Complete") 'SenData a Finalizado
End Sub

Esta solución funciona perfecto. De nuevo, gracias.
 
Top