Azure / Azure/data-api-builder

[Bug]: Odd config file requirements to get "complex" cosmosdb_nosql to work

Abierto
#2,335 6 comentarios 1 reacción 2 asignados Reclamado por @sourabh1007 Ver en GitHub
bug cosmos triage
Lenguaje dominante
C#
Estrellas
1.5k
Forks
370
Merge medio
3 d 22 h
PR fusionados (30 d)
9

Descripción

### What happened?

I have the following `cosmosdb_nosql` data setup with a database and 2 containers, `conferences` and `talks`:

data setup

- **database**
- conferences
- ```json
[
{
"endDate": "2022-06-01",
"id": "072d1638-a763-49f7-850f-763eed777837",
"location": "",
"mainTag": "",
"name": "CONFERENCE",
"startDate": "2022-06-01",
"url": "https://example.com/",
"year": 2022,
"talks": [
{
"abstract": "EXAMPLE",
"mainTag": "",
"tags": [],
"talkId": "0c8c7101-26ee-42e9-9596-32ec1d229c0b",
"talkLength": 50,
"talkTime": null,
"title": "EXAMPLE"
}
]
}
]
- talks
- ```json
[
{
"id": "f45a36c0-4031-4779-9461-eeedf37a7b74",
"mainTag": "Software Development",
"title": "EXAMPLE"
}
]
```

The important thing to notice is that there are **3** models, of which **2** need to be exposed as their own entities in DAB:
- Conference (**Exposable**)
- Talk (**Exposable**)
- ConferenceTalk
- Part of `Conference`, but not its own entity that needs to be exposed!

I [read the docs](https://learn.microsoft.com/en-us/azure/data-api-builder/quickstart-nosql#create-configuration-files) which tell me I need to define a graphql schema, on top of the `dab-config.json`, which I imagine has to look like this:

GraphQL schema

```graphql
type Conference @model {
id: ID!
name: String!
location: String
year: Int!
startDate: String
endDate: String
url: String
mainTag: String
talks: [ConferenceTalk!]!
}

type ConferenceTalk {
talkId: ID!
title: String!
abstract: String
mainTag: String
talkTime: String
talkLength: Int
tags: [String]
}

type Talk @model {
id: ID!
title: String!
mainTag: String
}
```

Which leads me to my `dab-config.json`, which looks like this.

dab-config.json

```json
{
"$schema": "https://github.com/Azure/data-api-builder/releases/download/v1.2.10/dab.draft.schema.json",
"data-source": {
"database-type": "cosmosdb_nosql",
"connection-string": "@env('COSMOSDB_CONNECTIONSTRING')",
"options": {
"database": "database",
"container": null,
"schema": "schema.gql"
}
},
"runtime": {
"rest": {
"enabled": false,
"path": "/api",
"request-body-strict": true
},
"graphql": {
"enabled": true,
"path": "/graphql",
"allow-introspection": true
},
"host": {
"cors": {
"origins": [],
"allow-credentials": false
},
"authentication": {
"provider": "StaticWebApps"
},
"mode": "development"
}
},
"entities": {
"Conference": {
"source": {
"object": "conferences"
},
"graphql": {
"enabled": true,
"type": {
"singular": "Conference",
"plural": "Conferences"
}
},
"rest": {
"enabled": false
},
"permissions": [
{
"role": "anonymous",
"actions": [
{
"action": "read"
}
]
}
]
},
"Talk": {
"source": {
"object": "talks"
},
"graphql": {
"enabled": true,
"type": {
"singular": "Talk",
"plural": "Talks"
}
},
"rest": {
"enabled": false
},
"permissions": [
{
"role": "anonymous",
"actions": [
{
"action": "read"
}
]
}
]
},
"ConferenceTalk": {
"source": {
"object": "WE_DO_NOT_EXPOSE_THIS_BUT_NEED_IT_TO_GET_DAB_TO_WORK"
},
"graphql": {
"enabled": false
},
"rest": {
"enabled": false
},
"permissions": [
{
"role": "anonymous",
"actions": [
{
"action": "read"
}
]
}
]
}
}
}
```

# The problem
I struggled with this for a **long** while. In order to get both `ConferenceTalk` and `Talk` to work, I must define `ConferenceTalk` as an entity in `dab-config.json`, which is what the error also says. However, this doesn't make sense because `ConferenceTalk` is not its own entity and should not need to be exposed.

# Expected solution
I should not need to define entities like `ConferenceTalk` in `dab-config.json` for objects that are part of main/parent entities. What if I had objects 10 layers deep? Would I need to define all of them as entities in `dab-config.json`? This would lead to a huge `dab-config.json` with filler data, just like `ConferenceTalk` is now.

## Extra
Please improve the docs about defining graphql yourself for cosmosdb. They're very limited. I have no idea why/if I need to define `@model`, for example.

### Version

Microsoft.DataApiBuilder 1.2.10+c7ca8db8558a63919c530e454c8f18b45d5b931c

### What database are you using?

CosmosDB NoSQL

### What hosting model are you using?

Local (including CLI)

### Which API approach are you accessing DAB through?

GraphQL

### Relevant log output

```Text
Azure.DataApiBuilder.Service.Startup[0]
Unable to complete runtime initialization. Refer to exception for error details.
Azure.DataApiBuilder.Service.Exceptions.DataApiBuilderException: The entity 'ConferenceTalk' was not found in the runtime config.
at Azure.DataApiBuilder.Core.Services.MetadataProviders.CosmosSqlMetadataProvider.AssertIfEntityIsAvailableInConfig(String entityName) in /_/src/Core/Services/MetadataProviders/CosmosSqlMetadataProvider.cs:line 296
at Azure.DataApiBuilder.Core.Services.MetadataProviders.CosmosSqlMetadataProvider.ProcessSchema(IReadOnlyList`1 fields, Dictionary`2 schemaDocument, String currentPath, IncrementingInteger tableCounter, EntityDbPolicyCosmosModel parentEntity, HashSet`1 visitedEntities) in /_/src/Core/Services/MetadataProviders/CosmosSqlMetadataProvider.cs:line 228
at Azure.DataApiBuilder.Core.Services.MetadataProviders.CosmosSqlMetadataProvider.ParseSchemaGraphQLFieldsForJoins() in /_/src/Core/Services/MetadataProviders/CosmosSqlMetadataProvider.cs:line 180
at Azure.DataApiBuilder.Core.Services.MetadataProviders.CosmosSqlMetadataProvider..ctor(RuntimeConfigProvider runtimeConfigProvider, IFileSystem fileSystem) in /_/src/Core/Services/MetadataProviders/CosmosSqlMetadataProvider.cs:line 85
at Azure.DataApiBuilder.Core.Services.MetadataProviders.MetadataProviderFactory..ctor(RuntimeConfigProvider runtimeConfigProvider, IAbstractQueryManagerFactory queryManagerFactory, ILogger`1 logger, IFileSystem fileSystem, Boolean isValidateOnly) in /_/src/Core/Services/MetadataProviders/MetadataProviderFactory.cs:line 32
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithManyArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier serviceIdentifier)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Azure.DataApiBuilder.Service.Startup.PerformOnConfigChangeAsync(IApplicationBuilder app) in /_/src/Service/Startup.cs:line 620
fail: Azure.DataApiBuilder.Service.Startup[0]
Could not initialize the engine with the runtime config file: dab-config.json
info: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
fail: Microsoft.Extensions.Hosting.Internal.Host[11]
Hosting failed to start
System.Threading.Tasks.TaskCanceledException: A task was canceled.
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.BindAsync(CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl.StartAsync[TContext](IHttpApplication`1 application, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync(CancellationToken cancellationToken)
at Microsoft.Extensions.Hosting.Internal.Host.b__15_1(IHostedService service, CancellationToken token)
at Microsoft.Extensions.Hosting.Internal.Host.ForeachService[T](IEnumerable`1 services, CancellationToken token, Boolean concurrent, Boolean abortOnFirstException, List`1 exceptions, Func`3 operation)
Unable to launch the Data API builder engine.
Error: Failed to start the engine.
```

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.