Upgrade to SDK 1.3.0 issue - :ERR_CONNECTION_REFUSED

I noticed since my upgrade today to SDK 1.3.0 that

when I start the JSON-API with createSchema=true only 1 table is added to the Database.
Previously 3 tables were added. in SDK 1.2.0

I also am getting the following error

VM30:1 POST http://localhost:3000/v1/query net::ERR_CONNECTION_REFUSED
(anonymous) @ VM30:1
post @ UserContext.js:93
fetchUpdate @ UserContext.js:113
loginUser @ UserContext.js:137
onClick @ Login.js:103
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:306
executeDispatch @ react-dom.development.js:389
executeDispatchesInOrder @ react-dom.development.js:414
executeDispatchesAndRelease @ react-dom.development.js:3278
executeDispatchesAndReleaseTopLevel @ react-dom.development.js:3287
forEachAccumulated @ react-dom.development.js:3259
runEventsInBatch @ react-dom.development.js:3304
runExtractedPluginEventsInBatch @ react-dom.development.js:3514
handleTopLevel @ react-dom.development.js:3558
batchedEventUpdates$1 @ react-dom.development.js:21871
batchedEventUpdates @ react-dom.development.js:795
dispatchEventForLegacyPluginEventSystem @ react-dom.development.js:3568
attemptToDispatchEvent @ react-dom.development.js:4267
dispatchEvent @ react-dom.development.js:4189
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11039
discreteUpdates$1 @ react-dom.development.js:21887
discreteUpdates @ react-dom.development.js:806
dispatchDiscreteEvent @ react-dom.development.js:4168
UserContext.js:151 roleOperator
index.js:529 WebSocket connection to ‘ws://localhost:7575/v1/stream/query’ failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

My code was previously working on SDK 1.2.0

Can you advise ?

1 Like

Can you share the output you get from daml json-api both from the schema initialization as well as when you’re actually starting it afterwards? Connection refused likely means that it failed to start somehow.

As for the number of tables, you should still get 3 tables in 1.3.0 (template_id, ledger_offset and contract). Hopefully the output from the initialization provides some information as to what went wrong. That said, the database schema of the json-api is an implementation detail and not something you should rely on. Of course, it might still be useful for debugging what went wrong.

Note that the JSON API does not store any persistent data, it only caches things in the database so one thing you could try is to delete the database completely and recreate it and then start the JSON API with
createSchema=true again.

The createSchema=true appears to be working

See attached file for output.

It also appears that the overall structure of the DB has changed in SDK1.3.0 as the total of tables as been reduced from 21 to 19 tables

This is my command to startup the JSON-API
daml json-api --ledger-host localhost --ledger-port 6865 --http-port 7575 --max-inbound-message-size 4194304 --package-reload-interval 5s --application-id HTTP-JSON-API-Gateway --static-content "prefix=static,directory=./static-content" --access-token-file ./token/token --query-store-jdbc-config "driver=org.postgresql.Driver,url=jdbc:postgresql://localhost:5432/test?&ssl=false,user=Bart,password=password,createSchema=false"

As far as the output of my regular startup of the JSON-API. Here is the output. (made it a daml file to be able to upload the file)

jsonoutput.daml (4.3 KB)

Note: I have not changed the token that is is located in the /token directory

Note 2 : a direct Post via Postman with the same bearer token appears to be working

Here is the code that is triggering the connection Error

UserContext,js

import React from “react”;

import { createToken, dablLoginUrl } from "../config";

var UserStateContext = React.createContext();

var UserDispatchContext = React.createContext();

function userReducer(state, action) {

  switch (action.type) {

    case "LOGIN_SUCCESS":

      return { ...state, isAuthenticated: true, token: action.token, party: action.party, role: action.role };

    case "LOGIN_FAILURE":

      return { ...state, isAuthenticated: false };

    case "SIGN_OUT_SUCCESS":

      return { ...state, isAuthenticated: false };

    default: {

      throw new Error(`Unhandled action type: ${action.type}`);

    }

  }

}

function UserProvider({ children }) {

  const party = localStorage.getItem("daml.party")

  const token = localStorage.getItem("daml.token")

  const role = localStorage.getItem("daml.role")

  var [state, dispatch] = React.useReducer(userReducer, {

    isAuthenticated: !!token,

    token,

    party,

    role

  });

  return (

    <UserStateContext.Provider value={state}>

      <UserDispatchContext.Provider value={dispatch}>

        {children}

      </UserDispatchContext.Provider>

    </UserStateContext.Provider>

  );

}

function useUserState() {

  var context = React.useContext(UserStateContext);

  if (context === undefined) {

    throw new Error("useUserState must be used within a UserProvider");

  }

  return context;

}

function useUserDispatch() {

  var context = React.useContext(UserDispatchContext);

  if (context === undefined) {

    throw new Error("useUserDispatch must be used within a UserProvider");

  }

  return context;

}

async function loginUser(dispatch, party, userToken, history, setIsLoading, setError) {

  setError(false);

  setIsLoading(true);

  const token =

    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwczovL2RhbWwuY29tL2xlZGdlci1hcGkiOnsibGVkZ2VySWQiOiJDb3ZpZDE5IiwiYXBwbGljYXRpb25JZCI6ImZvb2JhciIsImFjdEFzIjpbIk9wZXJhdG9yIl0sInJlYWRBcyI6WyJPcGVyYXRvciJdfX0.JklciDh0-GzkvrPkSJ_H3sYX39LFU4C3uVWd7qsMPNo"

  const headers = {

    "Authorization": `Bearer ${token.toString()}`,

    'Content-Type': 'application/json'

  }

  const siteSubDomain = (path = '/data/') => {

    if (window.location.hostname === 'localhost') {

      return window.location.hostname + (window.location.port ? ':' + window.location.port : '');

    }

    let host = window.location.host.split('.')

    const ledgerId = host[0];

    let apiUrl = host.slice(1)

    apiUrl.unshift('api')

    return apiUrl.join('.') + (window.location.port ? ':' + window.location.port : '') + path + ledgerId;

  }

  const post = (url, options = {}) => {

    Object.assign(options, { method: 'POST', headers });

    return fetch('//' + siteSubDomain() + url, options);

  }

  const fetchPublicToken = async () => {

    const response = await fetch('//' + siteSubDomain('/api/ledger/') + '/public/token', { method: 'POST' });

    const jsonResp = await response.json();

    const accessToken = jsonResp['access_token'];

    return accessToken;

  }

  let role = 'Citizen';

  if (!!party) {

    // NEW CODE HERE TO RETRIEVE ROLE FROM CITIZEN (Role data element)

    let failedStatus = false;

    const fetchUpdate = async () => {

      console.log("insidefetch");

      try {

        const contractResponse = await post('/v1/query', {

          body: JSON.stringify({

            "templateIds": ["Main:PartyInvitation"],

            "query": { "party": party }

          })

        });

        const citizenContractResponse = await contractResponse.json();

        if (citizenContractResponse.status === 200) {

          role = citizenContractResponse.result[0].payload.roletype

          console.log(role);

        }

      }

      catch (err) {

        alert("Something went wrong with roletype");

        role = party;

        // dispatch({ type: "LOGIN_FAILURE" });

        // setError(true);

        // setIsLoading(false);

        // failedStatus = true;

      }

    };

    await fetchUpdate();

    // if (failedStatus) return;

    // const token = userToken || createToken(party)

    localStorage.setItem("daml.party", party);

    localStorage.setItem("daml.token", token);

    // Role is retrieved from party Name

    // const role = localStorage.getItem("daml.party",party)

    localStorage.setItem("daml.role", role);

    dispatch({ type: "LOGIN_SUCCESS", token, party, role });

    console.log("role" + role);

    setError(null);

    setIsLoading(false);

    history.push("/app");

  } else {

    dispatch({ type: "LOGIN_FAILURE" });

    setError(true);

    setIsLoading(false);

  }

}

const loginDablUser = () => {

  window.location.assign(`https://${dablLoginUrl}`);

}

function signOut(event, dispatch, history) {

  event.preventDefault();

  localStorage.removeItem("daml.party");

  localStorage.removeItem("daml.token");

  // remove rand state

  localStorage.removeItem("daml.role");

  dispatch({ type: "SIGN_OUT_SUCCESS" });

  history.push("/login");

}

export { UserProvider, useUserState, useUserDispatch, loginUser, loginDablUser, signOut };
1 Like

Looking at this again, I expect the database stuff is a red herring. CONNECTION_REFUSED usually arises if nothing is listening on the port or that the port is blocked, e.g., by a firewall. Is the issue reproducible and are you sure the JSON API is running before you make the request?

Not able to reproduce it right now.
It must have been a failed JSON-API connection at that time. Will monitor the situation

2 Likes

Glad to hear that you got it working!

1 Like