- 사용해 봤고, 좋은 아이디어
- 사용해 봤고, 나쁜 아이디어
- 아직 안 해봤지만, 흥미롭다
- 왜 이걸에 시간을 낭비하죠?
- 잘 모르겠는데…
- 기타
재밌네요, 며칠 전 제가 정확히 이렇게 했거든요!
Hasura/nuxt.js를 1년째 다양한 프로젝트에서 사용하고 있습니다.
Hasura는 매우 강력하고, 예정된 기능들도 매우 기대됩니다!
discourse 포럼을 매우 좋아하지만(Ruby와 Ember는 잘 몰라서요), Hasura를 여기에 적용해 보았습니다.
Ruby 개발자가 아니어서 설치가 필요했는데, Mac에서 개발 환경을 설치하는 데 몇 가지 문제가 있었습니다. cppjieba_rb gem 때문에 고생하고 있어요…
그래서 결국 이 덤프를 가져와서 PostgreSQL과 Hasura에 설정했습니다.
모든 테이블이 가져온 것 같습니다. 뷰는 하나만 있나요? (badge_posts)
모든 외래키 관계도 추적했기 때문에, 다음과 같은 쿼리를 수행할 수 있습니다:
{
posts {
id
user_id
bookmarks {
id
name
}
uploads {
id
url
}
}
}
지금은 여기까지 왔습니다…
와, 기대되네요. 실환경에서 Hasura 컨테이너를 실행해 보고 결과를 공유하겠습니다. 정보를 교환해 볼 수 있겠네요.
참고로, 실행 중인 Discourse의 Postgres 데이터베이스 서버에서 psql 셸을 실행하려면 docker exec --user postgres -it app psql -d discourse를 사용할 수 있습니다. 따라서 전체 덤프를 생성하려면 다음을 실행할 수 있습니다(이 경우 -t 옵션은 필요 없으므로 제거했습니다):
docker exec --user postgres -i app pg_dump -Fc -d discourse > discourse.sql.pgcustom
이제 이를 도커화된 postgres(docker pull postgres:10.12)에 복원하고 개발을 위해 Hasura에 연결할 수 있습니다(이제 별도의 데이터베이스이므로 읽기 전용 수준에서만 실제로 유용합니다).
프로덕션 수준으로 이를 수행하려면, Discourse가 제공하는 환경을 설정하고 Amazon RDS와 같은 서비스에 데이터베이스를 호스팅해야 합니다. 그러면 해당 데이터베이스에 대한 읽기 및 쓰기 액세스가 용이해집니다.
위 덤프를 로컬에 복원하려면:
- 도커 네트워크 생성:
docker network create discourse-dev-net
- 첫 번째 셸에서:
docker run --rm -it -p 2345:5432 -e POSTGRES_DB=discourse -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --name=discourse-dev-pg --network=discourse-dev-net postgres:10.12
(백그라운드에서 실행하려면 -it 대신 -d를 사용하면 됩니다. -p 2345:5432는 선택 사항이지만 호스트에서 postgres에 연결하려는 경우 편리합니다)
- 다른 셸에서 postgres에 discourse 사용자 생성(덤프에 필요):
docker run --rm -it -v /path/to/discourse.sql.pgcustom:/discourse.sql.pgcustom:ro -e PGPASSWORD=postgres --network=discourse-dev-net postgres:10.12 createuser -h discourse-dev-pg -U postgres -P discourse
(그 후 프롬프트에서 비밀번호를 두 번 입력합니다. 저는 discourse를 비밀번호로 사용했습니다)
- 복원 수행:
docker run --rm -i -v /home/dean/Downloads/discourse.sql.pgcustom:/discourse.sql.pgcustom:ro -e PGPASSWORD=postgres --network=discourse-dev-net postgres:10.12 pg_restore -h discourse-dev-pg -U postgres -d discourse /discourse.sql.pgcustom
- Hasura를 위 설정에 연결하려면:
docker run --rm -it --network=discourse-dev-net -p 1234:1234 -e HASURA_GRAPHQL_ENABLE_CONSOLE=true -e HASURA_GRAPHQL_DATABASE_URL=postgres://postgres:postgres@discourse-dev-pg:5432/discourse hasura/graphql-engine:v1.2.1 graphql-engine serve --server-port=1234
(이제 http://localhost:1234을 방문할 수 있습니다)
상속된 데이터베이스를 직접 다루어 보니, @Falco 님이 이 게시물에서 지적한 내용이 매우 명확하게 드러났습니다.
Postgres의 강력한 기능 중 거의 대부분이 활용되지 않고 있습니다. 로직의 거의 전부가 Ruby 쪽에서 처리되고 있죠.
따라서 제 결론은, 이 접근법 자체가 완전히 도움이 되지 않는다는 것입니다.
다른 방법으로는 Hasura의 원격 스키마 기능을 사용하는 것이 있지만, 이를 위해서는 Discourse가 REST가 아닌 GraphQL API를 제공해야 합니다… 따라서 이 역시 자체적으로는 큰 도움이 되지 않습니다.
하지만 기존 REST API를 GraphQL 레이어로 감싸는 방법이 있습니다. 이는 위에서 언급한 방법들보다(또는 그것들과 결합했을 때) 더 유망해 보입니다. 해당 기사에서는 시작할 수 있는 보일러플레이트 코드가 포함된 저장소를 안내하고 있습니다.
답변해 주셔서 감사합니다.
저는 도커를 아주 잘 다루지는 못하지만, 제 문제는 도커 쪽에 있는 것이 아닙니다. discourse 개발 환경을 설정할 수 없어서 데이터베이스가 없습니다… 그저 이 빈 덤프 파일만 있을 뿐입니다.
어쨌든, 저는 이 덤프를 Heroku 인스턴스에 바로 배포했습니다! 그래서 라이브로 직접 테스트해 보실 수 있습니다 ![]()
이 온라인 GraphiQL에 접속하여 아래 엔드포인트를 설정해 보세요:
https://discourse-hasura.herokuapp.com/v1/graphql
자유롭게 조작해 보실 수 있습니다! 관리자 비밀번호가 없으므로 mutation과 subscription도 수행할 수 있습니다…
Hasura에서 discourse를 테스트하면서 제가 발견한 바로는, 모든 커스텀 함수, 트리거, 계산 필드… 모두 Ruby로 정의되어 있습니다. 이식성 측면에서 좋지 않습니다 ![]()
큰 도움이 되지 않습니다. discourse GraphQL API가 없기 때문이죠. 하지만 이는 Hasura의 강력한 기능입니다. 저는 Stripe의 커스텀 GraphQL과 함께 이 기능을 많이 사용하고 있습니다. 만약 discourse GraphQL API가 있다면, 리모트 스키마를 통해 우리 자신의 GraphQL에 연결할 수 있을 것입니다!
네, 하지만 모든 스키마와 리졸버(resolver)를 직접 구축해야 합니다. 작업량이 상당합니다!
여기서는 discourse의 Open API를 사용하는 것이 더 나을 것 같습니다: https://docs.discourse.org/ (다운로드 버튼 참고), 그리고 https://graphql-mesh.com/docs/handlers/openapi와 같은 GraphQL 생성기를 함께 사용하면 됩니다.
가능한 한 빨리 시도해 보겠습니다…
오, 기대됩니다! graphql-mesh를 시도해 보았습니다.
하지만 https://docs.discourse.org/ 의 다운로드 버튼 아래에 있는 openapi 파일이 깨져 있는 것 같습니다 ![]()
여기에서 유효성을 검사해 봤는데, 다음과 같은 오류가 나네요:
Swagger schema validation failed.
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/3
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/3
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/3
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/2
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/1
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/0
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/0
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/0
JSON_OBJECT_VALIDATION_FAILED
Error: Swagger schema validation failed.
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/3
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/3
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/3
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/2
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/1
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/0
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/0
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/0
JSON_OBJECT_VALIDATION_FAILED
at o (https://apitools.dev/swagger-parser/online/js/bundle.min.js:1:73766)
at https://apitools.dev/swagger-parser/online/js/bundle.min.js:17:227596
SyntaxError: Swagger schema validation failed.
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/3
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/3
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/3
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/2
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/2
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/1
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/0
Data does not match any schemas from 'oneOf' at #/paths//page_view_total_reqs/get/parameters/0
Missing required property: schema at #/
Missing required property: content at #/
Missing required property: $ref at #/paths//page_view_total_reqs/get/parameters/0
JSON_OBJECT_VALIDATION_FAILED
at Function.o [as syntax] (https://apitools.dev/swagger-parser/online/js/bundle.min.js:1:73766)
at validateSchema (https://apitools.dev/swagger-parser/online/js/bundle.min.js:1:5021)
at SwaggerParser.validate (https://apitools.dev/swagger-parser/online/js/bundle.min.js:1:3171)
z-schema validation error: JSON_OBJECT_VALIDATION_FAILED
at ZSchema.getLastError (https://apitools.dev/swagger-parser/online/js/bundle.min.js:17:211187)
at validateSchema (https://apitools.dev/swagger-parser/online/js/bundle.min.js:1:4925)
at SwaggerParser.validate (https://apitools.dev/swagger-parser/online/js/bundle.min.js:1:3171)
그래서 discourse API의 다른 openapi나 swagger 파일을 찾아보았습니다. 이것만 찾았네요.
426번째 줄이 조금 깨져 있긴 했지만, 제가 직접 수정했습니다.
graphql-mesh를 설정한 후, 작동하는 graphql API를 만들 수 있었습니다! 그런데…
이 swagger 파일은 불완전하거나 너무 오래된 것 같습니다. 쿼리가 4개뿐이고, mutation은 없으며, user 타입의 속성도 몇 개만 있네요… ![]()
discourse의 swagger나 openapi 파일을 구할 수 있는 곳이 있을까요?
유망해 보이는 작업입니다. 잘하셨습니다! Discourse가 Swagger/OpenAPI와 같은 오픈 스펙을 준수하면 좋겠습니다. 찾고 있는 정보를 찾기를 바랍니다.
지금 이 일에 쓸 시간이 많지 않지만, 나중에 다시 확인해 보겠습니다.
흥미로운 작업이네요. 현재 상태에서 어떤 graphql 쿼리가 가능한지 확인해볼 수 있도록 해당 코드를 어디에 공개해 두셨나요?
기타로 투표하려고 했는데 작동하지 않았습니다.
늦게 답변드려 죄송합니다. 질문을 놓쳤습니다.
네, discourse hasura graphql 엔드포인트로 플레이할 수 있습니다:
