Cardano-db-sync: Excepción debido a unicode en testnet

Creado en 19 sept. 2020  ·  15Comentarios  ·  Fuente: input-output-hk/cardano-db-sync

En la red testnet , cardano-db-sync en tags/5.0.0 en el modo extended , está lanzando excepciones en el bloque 1816809 debido a problemas de análisis / manejo de Unicode. No se puede sincronizar más allá de este bloque.

[db-sync-node:Info:234667] [2020-09-19 14:23:20.41 UTC] Starting chainSyncClient
[db-sync-node:Info:234667] [2020-09-19 14:23:20.48 UTC] Cardano.Db tip is at slot 6061839, block 1816809
[db-sync-node:Info:234672] [2020-09-19 14:23:20.48 UTC] Running DB thread
[db-sync-node:Info:234672] [2020-09-19 14:23:20.65 UTC] Rolling back to slot 6061839, hash 98414d12d1d1f05210dea6ce4082e1bcbbcfdf56343fd1cb44a8778c4c9ea57a
[db-sync-node:Info:234672] [2020-09-19 14:23:20.66 UTC] Deleting blocks numbered: []
[db-sync-node:Error:234672] [2020-09-19 14:23:21.03 UTC] runDBThread: DbInsertException "TxMetadata" (SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""})
[db-sync-node:Error:234667] [2020-09-19 14:23:21.05 UTC] ChainSyncWithBlocksPtcl: DbInsertException "TxMetadata" (SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""})
[db-sync-node.Subscription:Error:234663] [2020-09-19 14:23:21.05 UTC] [String "Application Exception: LocalAddress {getFilePath = \"/run/cardano-node/node.socket\"} DbInsertException \"TxMetadata\" (SqlError {sqlState = \"22P05\", sqlExecStatus = FatalError, sqlErrorMsg = \"unsupported Unicode escape sequence\", sqlErrorDetail = \"\\\\u0000 cannot be converted to text.\", sqlErrorHint = \"\"})",String "SubscriptionTrace"]
[db-sync-node.ErrorPolicy:Error:4] [2020-09-19 14:23:21.05 UTC] [String "ErrorPolicyUnhandledApplicationException (DbInsertException \"TxMetadata\" (SqlError {sqlState = \"22P05\", sqlExecStatus = FatalError, sqlErrorMsg = \"unsupported Unicode escape sequence\", sqlErrorDetail = \"\\\\u0000 cannot be converted to text.\", sqlErrorHint = \"\"}))",String "ErrorPolicyTrace",String "LocalAddress {getFilePath = \"/run/cardano-node/node.socket\"}"]

Comentario más útil

Así es como se ve ahora con la corrección temporal:

[db-sync-node:Info:37] [2020-09-22 10:19:09.66 UTC] insertShelleyBlock: epoch 84, slot 6060000, block 1816721, hash 3ec15354c53deae4eb26a206cc3185f799e80bd09393f279bce7e53a7d633144
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Info:37] [2020-09-22 10:19:24.93 UTC] insertShelleyBlock: epoch 84, slot 6065000, block 1816973, hash 0ab0dd5c36c6eb480b8bbd05508be952c5ed8597a4e422af25bd80a905a9368d

Todos 15 comentarios

Este es un dolor ENORME en el cuello.

El tx metedata que se está insertando es

(1,S "\NUL\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX")

que se codifica como JSON:

"\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003"

que, por supuesto, no es UTF8 válido y, por lo tanto, la base de datos lo rechaza.

Peor aún, lo anterior está codificado como UTF8 por la biblioteca Haskell Text como se muestra, pero PostgreSQL luego lo rechaza.

Permítanme reiterar que es un dolor ENORME en el cuello.

La cadena en cuestión se decodifica en UTF8 por la biblioteca Haskell Text y luego se pasa a Postgres, lo que arroja una excepción SqlError . Intenté capturar esta excepción, pero la captura de la excepción no parece funcionar.

Puedo capturar y registrar la excepción:

[db-sync-node:Warning:37] [2020-09-21 00:26:18.77 UTC] insertTxMetadata: Failed to insert (1,S "\NUL...\ETX")
SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg
 = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""}

pero luego hay una segunda excepción:

[db-sync-node:Error:37] [2020-09-21 00:26:18.77 UTC] runDBThread: SqlError {sqlState = "25P02", sqlExecStatus = FatalError, sqlErrorMsg = "current transaction is aborted, commands ignored until end of transaction
 block", sqlErrorDetail = "", sqlErrorHint = ""}

Esto sugiere que necesito validar más completamente el JSON antes de la inserción.

Podemos almacenar UTF8 no válido en PostgreSQL, pero solo como bytea datos, no como jsonb y si optamos por el soporte de consulta JSON de Postgres anterior no estará disponible.

He probado una decodificación UTF8 manual:

decodeUtf8IO :: ByteString -> IO (Either Text.UnicodeException Text)
decodeUtf8IO = try . evaluate . Text.decodeUtf8With Text.strictDecode

y eso también tiene el mismo problema.

De: https://stackoverflow.com/questions/31671634/handling-unicode-sequences-in-postgresql

Un byte nulo no es legal en una cadena de PostgreSQL. Tampoco es un punto de código cero.

Actualmente creo que esto se debe a la forma en que Haskell / Persistent serializa esto para enviarlo a postgres. Actualmente intentando validar esta teoría.

Aeson.encode ya escapa del carácter NUL a \u0000 que Persistent luego rechaza.

Encontrar una buena solución para esto no será fácil.

Estaba investigando esto y parece que estas propiedades se mantienen:

  • "\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003" es bastante válido como UTF-8, ya que UTF-8 permite que \u0000 se represente directamente.
  • \u0000 no está permitido para jsonb porque no se puede convertir a text .

La única solución temporal para codificarlo en un JSON, y luego en Text y luego detectar la secuencia de caracteres incorrecta y rechazar el objeto JSON si contiene la secuencia incorrecta. También me pregunto si \u0000 es la única secuencia que necesito rechazar,

¿No podrías almacenar dos columnas? el bytea y el JSON cuando no contiene el carácter que no es de texto, para que cualquiera sea libre de usar lo que necesite.

@erikd La \u0000 se establece claramente aquí , junto con todas las demás reglas que sigue Postgres. En pocas palabras: se están produciendo rechazos y transformaciones.

Para evitar una abstracción con fugas, se deben almacenar los valores exactos (proporcionados por el usuario). Esto significa aproximadamente un blob (= sin estructura en la base de datos) o valores de cadena JSON que de alguna manera conservan el significado original: por ejemplo, valores de cadena codificados en base64 en la base de datos (recuperando la estructura a expensas del procesamiento adicional en la aplicación en para traducir de base64 al valor real).

La solución temporal (simplemente eliminar objetos de metadatos que no se pueden insertar en Postgres) se ha fusionado con master.

Así es como se ve ahora con la corrección temporal:

[db-sync-node:Info:37] [2020-09-22 10:19:09.66 UTC] insertShelleyBlock: epoch 84, slot 6060000, block 1816721, hash 3ec15354c53deae4eb26a206cc3185f799e80bd09393f279bce7e53a7d633144
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Info:37] [2020-09-22 10:19:24.93 UTC] insertShelleyBlock: epoch 84, slot 6065000, block 1816973, hash 0ab0dd5c36c6eb480b8bbd05508be952c5ed8597a4e422af25bd80a905a9368d

Si Docker está reparado y cuál es la versión reparada

No está arreglado, pero 5.0.x (pero recomendaría 5.0.2 ) tiene una solución que evita este problema eliminando tx_metadata contiene el carácter Unicode NUL .

¿Fue útil esta página
0 / 5 - 0 calificaciones