Skip to content

Commit

Permalink
Merge branch 'master' into issue-1182-cache-update
Browse files Browse the repository at this point in the history
  • Loading branch information
rakeshkky committed Feb 8, 2019
2 parents a79a6cc + 9a6fa7f commit 428f70d
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,21 @@ class ModifyCustomFunction extends React.Component {
}
componentDidMount() {
const { functionName, schema } = this.props.params;
if (!functionName) {
if (!functionName || !schema) {
this.props.dispatch(push(prefixUrl));
}
Promise.all([
this.props.dispatch(fetchCustomFunction(functionName, schema)),
]);
}
componentWillReceiveProps(nextProps) {
const { functionName, schema } = this.props.params;
if (functionName !== nextProps.params.functionName || schema !== nextProps.params.schema) {
Promise.all([
this.props.dispatch(fetchCustomFunction(nextProps.params.functionName, nextProps.params.schema)),
]);
}
}
loadRunSQLAndLoadPage() {
const { functionDefinition } = this.props.functions;
Promise.all([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';

import Helmet from 'react-helmet';
import CommonTabLayout from '../../../Layout/CommonTabLayout/CommonTabLayout';
import { Link } from 'react-router';
// import { Link } from 'react-router';
import { push } from 'react-router-redux';

import { pageTitle, appPrefix } from '../Modify/constants';
Expand All @@ -16,21 +16,25 @@ import { fetchCustomFunction } from '../customFunctionReducer';

class Permission extends React.Component {
componentDidMount() {
const { functionName } = this.props.params;
const { functionName, schema } = this.props.params;
if (!functionName) {
this.props.dispatch(push(prefixUrl));
}
Promise.all([this.props.dispatch(fetchCustomFunction(functionName))]);
Promise.all([
this.props.dispatch(fetchCustomFunction(functionName, schema)),
]);
}
render() {
const styles = require('../Modify/ModifyCustomFunction.scss');
const {
functionSchema: schema,
functionName,
setOffTable,
setOffTableSchema,
} = this.props.functions;

const baseUrl = `${appPrefix}/schema/${schema}/functions/${functionName}`;
const permissionTableUrl = `${appPrefix}/schema/${schema}/tables/${setOffTable}/permissions`;
const permissionTableUrl = `${prefixUrl}/schema/${setOffTableSchema}/tables/${setOffTable}/permissions`;

const breadCrumbs = [
{
Expand Down Expand Up @@ -78,14 +82,14 @@ class Permission extends React.Component {
applicable to the data returned by this function
</p>
<div className={styles.commonBtn}>
<Link to={permissionTableUrl}>
<a href={permissionTableUrl}>
<button
className={styles.yellow_button}
data-test={'custom-function-permission-btn'}
>
{`${setOffTable} Permissions`}
</button>
</Link>
</a>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,25 @@ const fetchCustomFunction = (functionName, schema) => {
const deleteFunctionSql = () => {
return (dispatch, getState) => {
const currentSchema = getState().tables.currentSchema;
const functionName = getState().functions.functionName;
const functionDefinition = getState().functions.functionDefinition;
const sqlDropFunction =
'DROP FUNCTION ' +
'"' +
currentSchema +
'"' +
'.' +
'"' +
functionName +
'"';
const {
functionName,
functionDefinition,
inputArgTypes,
} = getState().functions;
let functionWSchemaName =
'"' + currentSchema + '"' + '.' + '"' + functionName + '"';

if (inputArgTypes.length > 0) {
let functionString = '(';
inputArgTypes.forEach((i, index) => {
functionString +=
i + ' ' + (index === inputArgTypes.length - 1 ? ')' : ',');
});
functionWSchemaName += functionString;
}

const sqlDropFunction = 'DROP FUNCTION ' + functionWSchemaName;

const sqlUpQueries = [
{
type: 'run_sql',
Expand All @@ -203,9 +211,11 @@ const deleteFunctionSql = () => {
const errorMsg = 'Deleting function failed';

const customOnSuccess = () => {
dispatch(_push('/'));
dispatch(_push(`/schema/${currentSchema}`));
};
const customOnError = () => {
dispatch({ type: DELETE_CUSTOM_FUNCTION_FAIL });
};
const customOnError = () => {};

dispatch({ type: DELETING_CUSTOM_FUNCTION });
return dispatch(
Expand Down Expand Up @@ -318,6 +328,9 @@ const customFunctionReducer = (state = functionData, action) => {
functionSchema: action.data[0][0].function_schema || null,
functionDefinition: action.data[1][0].function_definition || null,
setOffTable: action.data[1][0].return_type_name || null,
setOffTableSchema: action.data[1][0].return_type_schema || null,
inputArgNames: action.data[1][0].input_arg_names || null,
inputArgTypes: action.data[1][0].input_arg_types || null,
isFetching: false,
isFetchError: null,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const functionData = {
functionSchema: '',
functionDefinition: '',
setOffTable: '',
setOffTableSchema: '',
inputArgNames: [],
inputArgTypes: [],
...asyncState,
};

Expand Down
9 changes: 6 additions & 3 deletions install-manifests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ Various installation / deployment methods for Hasura GraphQL Engine

1. [Docker Compose](docker-compose)
2. [Docker Compose with HTTPS using Caddy](docker-compose-https)
3. [Docker run](docker-run)
3. [Kubernetes](kubernetes)

3. [Docker Compose with PostGIS enabled Postgres](docker-compose-postgis)
4. [Docker Compose with pgAdmin](docker-compose-pgadmin)
5. [Docker run](docker-run)
6. [Kubernetes](kubernetes)
7. [Azure Container Instance without Postgres](azure-container)
8. [Azure Container Instances with Postgres](azure-container-with-pg)

## License

Expand Down
36 changes: 36 additions & 0 deletions install-manifests/docker-compose-pgadmin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Hasura GraphQL Engine on Docker with pgAdmin

This Docker Compose setup runs [Hasura GraphQL Engine](https://github.com/hasura/graphql-engine) along with Postgres and [pgAdmin4](https://www.pgadmin.org/) using `docker-compose`.

## Pre-requisites

- [Docker](https://docs.docker.com/install/)
- [Docker Compose](https://docs.docker.com/compose/install/)

## Usage

- Clone this repo on a machine where you'd like to deploy graphql engine
- Edit `docker-compose.yaml` and change `PGADMIN_DEFAULT_EMAIL` and `PGADMIN_DEFAULT_PASSWORD` to something secure (default pgAdmin login email/password) default value for above variables are:
- **PGADMIN_DEFAULT_EMAIL:** `[email protected]`
- **PGADMIN_DEFAULT_PASSWORD:** `admin`
- Read more `Environment Variables` here: https://hub.docker.com/r/dpage/pgadmin4/
- Edit `docker-compose.yaml` and change `HASURA_GRAPHQL_ACCESS_KEY` to something secure
- `docker-compose up -d`
- Navigate to `http://localhost:5050`, login and add a new server with the following parameters:
General - Name: Hasura
Connection - Host: `hasura`
Username: `postgres`
Password: leave empty

## Important endpoints

- GraphQL endpoint will be `http://localhost:8080/v1alpha1/graphql`
- Hasura Console will be available on `http://localhost:8080/console`
- pgAdmin will be available on `http://localhost:5050`


## Connecting to External Postgres

If you want to connect to an external/existing postgres database, replace `HASURA_GRAPHQL_DATABASE_URL` in `docker-compose.yaml` with your database url.

**Note: localhost will resolve to the container ip inside a docker container, not the host ip**
32 changes: 32 additions & 0 deletions install-manifests/docker-compose-pgadmin/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
version: '3.6'
services:
postgres:
image: postgres
restart: always
volumes:
- db_data:/var/lib/postgresql/data
pgadmin:
image: dpage/pgadmin4
restart: always
depends_on:
- postgres
ports:
- 5050:80
## you can change pgAdmin default username/password with below environment variables
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD: admin
graphql-engine:
image: hasura/graphql-engine:v1.0.0-alpha37
ports:
- "8080:8080"
depends_on:
- "postgres"
restart: always
environment:
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:@postgres:5432/postgres
HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console
## uncomment next line to set an access key
# HASURA_GRAPHQL_ACCESS_KEY: mysecretaccesskey
volumes:
db_data:
70 changes: 50 additions & 20 deletions server/src-lib/Hasura/Events/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ data TriggerMeta

$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''TriggerMeta)

data DeliveryInfo
= DeliveryInfo
{ diCurrentRetry :: Int
, diMaxRetries :: Int
} deriving (Show, Eq)

$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''DeliveryInfo)

data Event
= Event
{ eId :: EventId
Expand All @@ -75,18 +83,29 @@ data Event
, eCreatedAt :: Time.UTCTime
} deriving (Show, Eq)

instance ToJSON Event where
toJSON (Event eid (QualifiedObject sn tn) trigger event _ created)=
object [ "id" .= eid
, "table" .= object [ "schema" .= sn
, "name" .= tn
]
, "trigger" .= trigger
, "event" .= event
, "created_at" .= created
$(deriveFromJSON (aesonDrop 1 snakeCase){omitNothingFields=True} ''Event)

newtype QualifiedTableStrict = QualifiedTableStrict
{ getQualifiedTable :: QualifiedTable
} deriving (Show, Eq)

instance ToJSON QualifiedTableStrict where
toJSON (QualifiedTableStrict (QualifiedObject sn tn)) =
object [ "schema" .= sn
, "name" .= tn
]

$(deriveFromJSON (aesonDrop 1 snakeCase){omitNothingFields=True} ''Event)
data EventPayload
= EventPayload
{ epId :: EventId
, epTable :: QualifiedTableStrict
, epTrigger :: TriggerMeta
, epEvent :: Value
, epDeliveryInfo :: DeliveryInfo
, epCreatedAt :: Time.UTCTime
} deriving (Show, Eq)

$(deriveToJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''EventPayload)

data WebhookRequest
= WebhookRequest
Expand Down Expand Up @@ -266,6 +285,17 @@ tryWebhook logenv pool e = do
eventId = eId e
headerInfos = etiHeaders eti
headers = map encodeHeader headerInfos
eventPayload = EventPayload
{ epId = eId e
, epTable = QualifiedTableStrict { getQualifiedTable = eTable e}
, epTrigger = eTrigger e
, epEvent = eEvent e
, epDeliveryInfo = DeliveryInfo
{ diCurrentRetry = eTries e
, diMaxRetries = rcNumRetries $ etiRetryConf eti
}
, epCreatedAt = eCreatedAt e
}
eeCtx <- asks getter
-- wait for counter and then increment beforing making http
liftIO $ atomically $ do
Expand All @@ -276,7 +306,7 @@ tryWebhook logenv pool e = do
else modifyTVar' c (+1)
let options = addHeaders headers W.defaults
decodedHeaders = map (decodeHeader headerInfos) $ options CL.^. W.headers
eitherResp <- runExceptT $ runHTTP options (mkAnyHTTPPost (T.unpack webhook) (Just $ toJSON e)) (Just (ExtraContext createdAt eventId))
eitherResp <- runExceptT $ runHTTP options (mkAnyHTTPPost (T.unpack webhook) (Just $ toJSON eventPayload)) (Just (ExtraContext createdAt eventId))

--decrement counter once http is done
liftIO $ atomically $ do
Expand All @@ -287,32 +317,32 @@ tryWebhook logenv pool e = do
Left err ->
case err of
HClient excp -> let errMsg = TBS.fromLBS $ encode $ show excp
in runFailureQ pool $ mkInvo e 1000 decodedHeaders errMsg []
in runFailureQ pool $ mkInvo eventPayload 1000 decodedHeaders errMsg []
HParse _ detail -> let errMsg = TBS.fromLBS $ encode detail
in runFailureQ pool $ mkInvo e 1001 decodedHeaders errMsg []
in runFailureQ pool $ mkInvo eventPayload 1001 decodedHeaders errMsg []
HStatus errResp -> let respPayload = hrsBody errResp
respHeaders = hrsHeaders errResp
respStatus = hrsStatus errResp
in runFailureQ pool $ mkInvo e respStatus decodedHeaders respPayload respHeaders
in runFailureQ pool $ mkInvo eventPayload respStatus decodedHeaders respPayload respHeaders
HOther detail -> let errMsg = (TBS.fromLBS $ encode detail)
in runFailureQ pool $ mkInvo e 500 decodedHeaders errMsg []
in runFailureQ pool $ mkInvo eventPayload 500 decodedHeaders errMsg []
Right resp -> let respPayload = hrsBody resp
respHeaders = hrsHeaders resp
respStatus = hrsStatus resp
in runSuccessQ pool e $ mkInvo e respStatus decodedHeaders respPayload respHeaders
in runSuccessQ pool e $ mkInvo eventPayload respStatus decodedHeaders respPayload respHeaders
case finally of
Left err -> liftIO $ logger $ L.toEngineLog $ EventInternalErr err
Right _ -> return ()
return eitherResp
where
mkInvo :: Event -> Int -> [HeaderConf] -> TBS.TByteString -> [HeaderConf] -> Invocation
mkInvo e' status reqHeaders respBody respHeaders
mkInvo :: EventPayload -> Int -> [HeaderConf] -> TBS.TByteString -> [HeaderConf] -> Invocation
mkInvo ep status reqHeaders respBody respHeaders
= let resp = if isInitError status then mkErr respBody else mkResp status respBody respHeaders
in
Invocation
(eId e')
(epId ep)
status
(mkWebhookReq (toJSON e) reqHeaders)
(mkWebhookReq (toJSON ep) reqHeaders)
resp
addHeaders :: [(N.HeaderName, BS.ByteString)] -> W.Options -> W.Options
addHeaders headers opts = foldl (\acc h -> acc CL.& W.header (fst h) CL..~ [snd h] ) opts headers
Expand Down

0 comments on commit 428f70d

Please sign in to comment.