msupply-foundation / unified-codes

Provides a curated, searchable list of pharmaceutical products, each with an immutable code. A GraphQL API, a REST API and website are available for interaction with the database.
https://codes.msupply.foundation
2 stars 0 forks source link

when approving drug it saved itself but does not appear in the drug list and says it already exists #616

Closed louisaw123 closed 6 months ago

louisaw123 commented 6 months ago

IMAGE 2024-03-21 10:17:53

Entered in diclofenac drug details to be submitted into system. On the approval process when i clicked approve it came up with big blob of text in a red box with warning - tried screenshotting this but it vanished.

my approval box did not change however so i thought it was not approved yet, clicked approve but this time says the drugs already have existing codes as below:

IMAGE 2024-03-21 10:18:03

tried searching for the drugs in the search bar and it comes up but nothing comes up to select in the big box area:

IMAGE 2024-03-21 10:18:15

jmbrunskill commented 6 months ago

Looks like this was caused by a transaction error from dGraph, our 3 retries wasn't enough :( Also our error handling clearly leaves things in an invalid state.

2024-03-20 20:47:19.037841981 [INFO] <graphql::logger:79>:[Execute] mutation approvePendingChange($id: String, $input: UpsertEntityInput!) { approvePendingChange(requestId: "2883f672-6916-4c2c-af3f-033f1f285fcd", input: {parentCode: "933f3f00", name: "Diclofenac", category: "Drug", properties: [{code: "",key: "code_rxnav",value: "3355"},{code: "",key: "code_nzulm",value: "10046291000116101"},{code: "",key: "code_unspsc",value: "51383304"},{code: "",key: "code_atc",value: "D11AX18"}], description: "Diclofenac", type: "Product", alternativeNames: [], children: [{name: "Rectal",category: "Drug",properties: [],description: "Diclofenac Rectal",type: "Route",children: [{name: "Suppository",category: "Drug",properties: [],description: "Diclofenac Rectal Suppository",type: "Form",children: [{name: "12.5mg",category: "Drug",properties: [{code: "",key: "code_rxnav",value: "857698"},{code: "",key: "code_nzulm_item",value: "10744861000116102"}],description: "Diclofenac Rectal Suppository 12.5mg",type: "DoseStrength",children: []},{name: "50mg",category: "Drug",properties: [{code: "",key: "code_rxnav",value: "857709"},{code: "",key: "code_nzulm_item",value: "10744701000116105"}],description: "Diclofenac Rectal Suppository 50mg",type: "DoseStrength",children: []}]}]},{name: "Oral",category: "Drug",properties: [],description: "Diclofenac Oral",type: "Route",children: [{name: "Tablet (enteric coated)",category: "Drug",properties: [],description: "Diclofenac Oral Tablet (enteric coated)",type: "Form",children: [{name: "25mg",category: "Drug",properties: [{code: "",key: "code_rxnav",value: "855663"},{code: "",key: "code_nzulm_item",value: "10054111000116107"}],description: "Diclofenac Oral Tablet (enteric coated) 25mg",type: "DoseStrength",children: []},{name: "50mg",category: "Drug",properties: [{code: "",key: "code_rxnav",value: "855681"},{code: "",key: "code_nzulm_item",value: "44270861000116104"}],description: "Diclofenac Oral Tablet (enteric coated) 50mg",type: "DoseStrength",children: []}]}]}]}) { ... on EntityType { __typename code } } }
2024-03-20 20:47:19.327372600 [ERROR] <dgraph::client:54>:Query failed, retrying - "\nmutation UpdateEntity($input: [AddEntityInput!]!, $upsert: Boolean = false) {\n  data: addEntity(input: $input, upsert: $upsert) {\n    numUids\n  }\n}" :
GQLClient Error: Failed to parse response: Error("invalid type: null, expected struct UpsertResponse", line: 1, column: 190). The response body is: {"errors":[{"message":"mutation failed, couldn't commit transaction because rpc error: code = Aborted desc = Transaction has been aborted. Please retry","path":["data"]}],"data":{"data":null},"extensions":{"touched_uids":19,"tracing":{"version":1,"startTime":"2024-03-20T20:47:19.309229777+01:00","endTime":"2024-03-20T20:47:19.316847397+01:00","duration":7617631,"execution":{"resolvers":[{"path":["data"],"parentType":"Mutation","fieldName":"data","returnType":"AddEntityPayload","startOffset":238914,"duration":7369124,"dgraph":[{"label":"preMutationQuery","startOffset":331638,"duration":1610795},{"label":"mutation","startOffset":2061404,"duration":2666863},{"label":"query","startOffset":0,"duration":0}]}]}}}}

2024-03-20 20:47:19.328902257 [ERROR] <dgraph::client:54>:Query failed, retrying - "\nmutation UpdateEntity($input: [AddEntityInput!]!, $upsert: Boolean = false) {\n  data: addEntity(input: $input, upsert: $upsert) {\n    numUids\n  }\n}" :
GQLClient Error: Failed to parse response: Error("invalid type: null, expected struct UpsertResponse", line: 1, column: 190). The response body is: {"errors":[{"message":"mutation failed, couldn't commit transaction because rpc error: code = Aborted desc = Transaction has been aborted. Please retry","path":["data"]}],"data":{"data":null},"extensions":{"touched_uids":19,"tracing":{"version":1,"startTime":"2024-03-20T20:47:19.310025627+01:00","endTime":"2024-03-20T20:47:19.317054038+01:00","duration":7028421,"execution":{"resolvers":[{"path":["data"],"parentType":"Mutation","fieldName":"data","returnType":"AddEntityPayload","startOffset":117924,"duration":6900253,"dgraph":[{"label":"preMutationQuery","startOffset":176165,"duration":1423074},{"label":"mutation","startOffset":1687727,"duration":3694129},{"label":"query","startOffset":0,"duration":0}]}]}}}}

2024-03-20 20:47:19.330329311 [ERROR] <dgraph::client:54>:Query failed, retrying - "\nmutation UpdateEntity($input: [AddEntityInput!]!, $upsert: Boolean = false) {\n  data: addEntity(input: $input, upsert: $upsert) {\n    numUids\n  }\n}" :
GQLClient Error: Failed to parse response: Error("invalid type: null, expected struct UpsertResponse", line: 1, column: 190). The response body is: {"errors":[{"message":"mutation failed, couldn't commit transaction be
cause rpc error: code = Aborted desc = Transaction has been aborted. Please retry","path":["data"]}],"data":{"data":null},"extensions":{"touched_uids":19,"tracing":{"version":1,"startTime":"2024-03-20T20:47:19.30951542
2+01:00","endTime":"2024-03-20T20:47:19.317403394+01:00","duration":7888003,"execution":{"resolvers":[{"path":["data"],"parentType":"Mutation","fieldName":"data","returnType":"AddEntityPayload","startOffset":144397,"du
ration":7734395,"dgraph":[{"label":"preMutationQuery","startOffset":189253,"duration":2336669},{"label":"mutation","startOffset":2618839,"duration":3636903},{"label":"query","startOffset":0,"duration":0}]}]}}}}

2024-03-20 20:47:19.395105469 [ERROR] <dgraph::client:54>:Query failed, retrying - "\nmutation UpdateEntity($input: [AddEntityInput!]!, $upsert: Boolean = false) {\n  data: addEntity(input: $input, upsert: $upsert) {\n
    numUids\n  }\n}" :
GQLClient Error: Failed to parse response: Error("invalid type: null, expected struct UpsertResponse", line: 1, column: 190). The response body is: {"errors":[{"message":"mutation failed, couldn't commit transaction be
cause rpc error: code = Aborted desc = Transaction has been aborted. Please retry","path":["data"]}],"data":{"data":null},"extensions":{"touched_uids":19,"tracing":{"version":1,"startTime":"2024-03-20T20:47:19.36762557
1+01:00","endTime":"2024-03-20T20:47:19.387477266+01:00","duration":19851684,"execution":{"resolvers":[{"path":["data"],"parentType":"Mutation","fieldName":"data","returnType":"AddEntityPayload","startOffset":163060,"d
uration":19678105,"dgraph":[{"label":"preMutationQuery","startOffset":255801,"duration":1699296},{"label":"mutation","startOffset":2035359,"duration":14831439},{"label":"query","startOffset":0,"duration":0}]}]}}}}

2024-03-20 20:47:19.396995787 [ERROR] <dgraph::client:54>:Query failed, retrying - "\nmutation UpdateEntity($input: [AddEntityInput!]!, $upsert: Boolean = false) {\n  data: addEntity(input: $input, upsert: $upsert) {\n
    numUids\n  }\n}" :
GQLClient Error: Failed to parse response: Error("invalid type: null, expected struct UpsertResponse", line: 1, column: 190). The response body is: {"errors":[{"message":"mutation failed, couldn't commit transaction be
cause rpc error: code = Aborted desc = Transaction has been aborted. Please retry","path":["data"]}],"data":{"data":null},"extensions":{"touched_uids":19,"tracing":{"version":1,"startTime":"2024-03-20T20:47:19.36735847
1+01:00","endTime":"2024-03-20T20:47:19.387731107+01:00","duration":20372655,"execution":{"resolvers":[{"path":["data"],"parentType":"Mutation","fieldName":"data","returnType":"AddEntityPayload","startOffset":430345,"d
uration":19934014,"dgraph":[{"label":"preMutationQuery","startOffset":526655,"duration":9612738},{"label":"mutation","startOffset":10305842,"duration":6377090},{"label":"query","startOffset":0,"duration":0}]}]}}}}

2024-03-20 20:47:19.444671079 [INFO] <graphql::logger:28>:[Execute Response] "approvePendingChange" - response_length: 1254
2024-03-20 20:47:19.444759340 [INFO] <graphql::logger:113>:[Error] path=approvePendingChange message=Internal error ext=Some(ErrorExtensionValues({"details": String("\nGQLClient Error: Failed to parse response: Error(\
"invalid type: null, expected struct UpsertResponse\", line: 1, column: 190). The response body is: {\"errors\":[{\"message\":\"mutation failed, couldn't commit transaction because rpc error: code = Aborted desc = Tran
saction has been aborted. Please retry\",\"path\":[\"data\"]}],\"data\":{\"data\":null},\"extensions\":{\"touched_uids\":19,\"tracing\":{\"version\":1,\"startTime\":\"2024-03-20T20:47:19.428759354+01:00\",\"endTime\":\
"2024-03-20T20:47:19.434692763+01:00\",\"duration\":5933423,\"execution\":{\"resolvers\":[{\"path\":[\"data\"],\"parentType\":\"Mutation\",\"fieldName\":\"data\",\"returnType\":\"AddEntityPayload\",\"startOffset\":1072
35,\"duration\":5816228,\"dgraph\":[{\"label\":\"preMutationQuery\",\"startOffset\":153171,\"duration\":1501964},{\"label\":\"mutation\",\"startOffset\":1754085,\"duration\":2424309},{\"label\":\"query\",\"startOffset\
":0,\"duration\":0}]}]}}}}\n - None")}))

Possible solution is to generate all new codes as part of saving/updating, and if there is an error save the pending changes record with the codes attached do a re-try should work?

The better solution is probably to put the whole transaction in as a single mutation but harder to achieve with our code base...