Tiamat é o Stop Place Register. É usado nacionalmente na Noruega e em outros lugares. Tiamat é criado com tecnologias como Spring Boot, Hibernate, Postgis, Jersey e Jackson.
Suporta a exportação de locais de parada e outras entidades para o formato http://netex-cen.eu/. Existem muitas opções de exportação:
Tiamat fornece uma API GraphQL rica para locais de parada, locais topográficos, links de caminho, zonas tarifárias e assim por diante, suportando os mesmos parâmetros da API de exportação NeTEx. Ele também suporta mutações. Assim você pode atualizar ou criar entidades. Existem também processos graphql (funções nomeadas) que permitem funcionalidades como mesclar cais ou locais de parada.
Um frontend para Tiamat está disponível. Seu nome é Abzu. Consulte https://github.com/entur/abzu
Tiamat usa grade de memória Hazelcast para se comunicar com outras instâncias em kubernetes. Isso significa que você pode executar várias instâncias.
Após importar os locais de parada e atribuir novos IDs aos locais de parada, o tiamat mantém os IDs antigos em uma tabela de mapeamento. A tabela de mapeamento entre IDs antigos e novos está disponível por meio da API GraphQL e de um endpoint REST.
Tiamat suporta a procura e o preenchimento de referências a zonas tarifárias e locais topográficos a partir de correspondências de polígonos ao salvar um local de parada.
Os locais de parada e outras entidades são versionados. Isso significa que você tem o histórico completo da versão dos locais de parada e a pessoa que fez essas alterações. Tiamat também inclui uma ferramenta de comparação. Isto é usado para comparar e mostrar a diferença entre duas versões de um local de parada (ou outra entidade).
mvn clean install
Você precisa do diretório /deployments/data
com direitos para o usuário que executa a compilação.
Tiamat usa testcontainers para executar testes de integração em um banco de dados real. Para executar testes baseados em Testcontainers, você precisa de um tempo de execução de contêiner compatível com Docker-API. Para obter mais detalhes, consulte https://www.testcontainers.org/supported_docker_environment/
(perfis padrão são definidos em application.properties)
Para executar o Tiamat com Docker compose, você precisa ter um arquivo docker-compose.yml. Na pasta docker-compose você encontrará um arquivo compose.yml.:
docker compose up
Isso iniciará o Tiamat com PostgreSQL e Hazelcast. e você pode acessar o Tiamat em http://localhost:1888 e o banco de dados em http://localhost:5433 e o graphiql em http://localhost:8777/services/stop_places/graphql. Na inicialização, o tiamat copie o esquema vazio para o banco de dados. As propriedades do Spring são definidas em application.properties. A segurança está desabilitada nesta configuração.
Para rodar com PostgreSQL você precisa de um application.properties externo. Abaixo está um exemplo de application.properties:
spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres
spring.jpa.properties.hibernate.hbm2ddl.import_files_sql_extractor=org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
spring.jpa.hibernate.hbm2ddl.import_files_sql_extractor=org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor
spring.jpa.hibernate.ddl-auto=none
spring.http.gzip.enabled=true
#spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.order_updates=true
spring.jpa.properties.hibernate.batch_versioned_data=true
spring.flyway.enabled=true
spring.flyway.table =schema_version
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain
spring.jpa.hibernate.id.new_generator_mappings=true
spring.jpa.hibernate.use-new-id-generator-mappings=true
spring.jpa.properties.hibernate.cache.use_second_level_cache=false
spring.jpa.properties.hibernate.cache.use_query_cache=false
spring.jpa.properties.hibernate.cache.use_minimal_puts=false
spring.jpa.properties.hibernate.cache.region.factory_class=org.rutebanken.tiamat.hazelcast.TiamatHazelcastCacheRegionFactory
netex.import.enabled.types=MERGE,INITIAL,ID_MATCH,MATCH
hazelcast.performance.monitoring.enabled=true
hazelcast.performance.monitoring.delay.seconds=2
management.endpoints.web.exposure.include=info,env,metrics
management.endpoints.prometheus.enabled=true
management.metrics.endpoint.export.prometheus.enabled=true
spring.jpa.properties.hibernate.jdbc.batch_size=20
spring.jpa.properties.hibernate.default_batch_fetch_size=16
spring.jpa.properties.hibernate.generate_statistics=false
changelog.publish.enabled=false
jettyMaxThreads=10
jettyMinThreads=1
spring.datasource.hikari.maximumPoolSize=40
spring.datasource.hikari.leakDetectionThreshold=30000
tiamat.locals.language.default=eng
tariffZoneLookupService.resetReferences=true
debug=true
# Disable feature detection by this undocumented parameter. Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
# Because detection is disabled you have to set correct dialect by hand.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
tariffzoneLookupService.resetReferences=true
spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect
spring.database.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5436/tiamat
spring.datasource.username=tiamat
spring.datasource.password=tiamat
#OAuth2 Resource Server
spring.security.oauth2.resourceserver.jwt.issuer-uri=https:http://localhost:8082/realms/entur
tiamat.oauth2.resourceserver.auth0.ror.jwt.audience=abzu
tiamat.oauth2.resourceserver.auth0.ror.claim.namespace=role_assignments
spring.cloud.gcp.pubsub.enabled=false
aspect.enabled=true
netex.id.valid.prefix.list={TopographicPlace:{'KVE','WOF','OSM','ENT','LAN'},TariffZone:{'*'},FareZone:{'*'},GroupOfTariffZones:{'*'}}
server.port=1888
blobstore.gcs.blob.path=exports
blobstore.gcs.bucket.name=tiamat-test
blobstore.gcs.credential.path=gcloud-storage.json
blobstore.gcs.project.id=carbon-1287
security.basic.enabled=false
management.security.enabled=false
authorization.enabled = true
rutebanken.kubernetes.enabled=false
async.export.path=/tmp
publicationDeliveryUnmarshaller.validateAgainstSchema=false
publicationDeliveryStreamingOutput.validateAgainstSchema=false
netex.validPrefix=NSR
netex.profile.version=1.12:NO-NeTEx-stops:1.4
blobstore.local.folder=/tmp/local-gcs-storage/tiamat/export
spring.profiles.active=local-blobstore,activemq
Para iniciar o Tiamat com esta configuração, especifique spring.config.location :
java -jar -Dspring.config.location=/path/to/tiamat.properties --add-opens java.base/java.lang=ALL-UNNAMED -Denv=dev tiamat-0.0.2-SNAPSHOT.jar
Tiamat está usando HikariCP. A maioria das propriedades deve poder ser especificada em application.properties, como spring.datasource.initializationFailFast=false
. Mais informações aqui. https://github.com/brettwooldridge/HikariCP/wiki/Configuration Consulte também http://stackoverflow.com/a/26514779
docker run -it -d -p 5435:5432 --name postgress-13 -e POSTGRES_USER=tiamat -e POSTGRES_PASSWORD="tiamat" -e POSTGRES_INITDB_ARGS="-d" postgis/postgis:13-master
Durante a implementação do Tiamat era desejável produzir IDs NeTEx para locais de parada com mais ou menos lacunas. O motivo desta implementação foram sistemas legados com restrições de número máximo de dígitos.
É possível controlar se os IDs devem ser gerados fora do Tiamat ou não. Veja a classe ValidPrefixList. Definir a propriedade netex.validPrefix
diz ao Tiamat para gerar IDs para novas entidades. Observe que não é possível fazer uma importação inicial (consulte ImportType) várias vezes com os mesmos IDs.
Tudo é iniciado por um ouvinte de entidade anotado com PrePersist
na classe IdentifiedEntity
chamada IdentifiedEntityListener
. NetexIdAssigner
determina se a entidade já possui um ID ou não. NetexIdProvider
retorna um novo ID ou lida com IDs reivindicados explicitamente se o prefixo configurado corresponder. Consulte ValidPrefixList
para a configuração de prefixos válidos e prefixos para IDs gerados em outro lugar. O GaplessIdGeneratorService
usa Hazelcast para sincronizar o estado entre instâncias e evitar conflitos.
Tanto o Tiamat quanto o Abzu estão configurados para serem usados com Keycloak ou Auth0. Um guia detalhado sobre como configurar o Keycloak pode ser encontrado aqui.
É possível configurar se o tiamat deve validar o xml NeTEx de entrada e saída ao desempacotar ou empacotar entregas de publicações. Os valores padrão são verdadeiros. Pode ser desativado definindo as propriedades como falsas.
publicationDeliveryStreamingOutput.validateAgainstSchema=false
publicationDeliveryUnmarshaller.validateAgainstSchema=true
É possível exportar paradas e locais topográficos diretamente para o formato NeTEx. Este é o ponto final: https://api.dev.entur.io/stop-places/v1/netex
https://api.dev.entur.io/stop-places/v1/netex?q=Arne%20Garborgs%20vei
https://api.dev.entur.io/stop-places/v1/netex?q=3115
https://api.dev.entur.io/stop-places/v1/netex?stopPlaceType=RAIL_STATION
Também é possível com vários tipos.
https://api.dev.entur.io/stop-places/v1/netex?municipalityReference=KVE:TopographicPlace:1003
https://api.dev.entur.io/stop-places/v1/netex?countyReference=KVE:TopographicPlace:11
https://api.dev.entur.io/stop-places/v1/netex?size=1000
https://api.dev.entur.io/stop-places/v1/netex?page=1
Você pode especificar uma lista de IDs de locais de parada NSR para retornar
https://api.dev.entur.io/stop-places/v1/netex?idList=NSR:StopPlace:3378&idList=NSR:StopPlace:123
allVersions
. Os valores aceitáveis são verdadeiros ou falsos. Se definido como verdadeiro, todas as versões dos locais de parada correspondentes serão retornadas. Se definido como falso, a versão mais alta por número será retornada para locais de parada correspondentes. Este parâmetro não é habilitado ao usar o parâmetro de validade de versão.
Corresponder apenas locais de parada sem localização Use o parâmetro: withoutLocationOnly=true
O parâmetro topographicPlaceExportMode
pode ser definido como NONE , RELEVANT ou ALL Locais topográficos relevantes serão encontrados na lista exportada de locais de parada.
O parâmetro tariffZoneExportMode
pode ser definido como NONE , RELEVANT ou ALL Zonas tarifárias relevantes que podem ser encontradas na lista exportada de locais de parada. Porque os locais de paragem podem ter uma lista de referências de zonas tarifárias.
O parâmetro groupOfStopPlacesExportMode
pode ser definido como NONE , RELEVANT ou ALL. O grupo relevante de locais de parada pode ser encontrado na lista exportada de locais de parada.
O parâmetro versionValidity
controla quais pontos de parada retornar.
https://api.dev.entur.io/stop-places/v1/netex?tariffZoneExportMode=RELEVANT&topographicPlaceExportMode=RELEVANT&groupOfStopPlacesExportMode=NONE&q=Nesbru&versionValidity=CURRENT&municipalityReference=KVE:TopographicPlace:0220
Retorna locais de parada com versão atual válida agora, correspondendo à consulta 'Nesbru' e existente no município 0220. Busca zonas tarifárias e locais topográficos relevantes.
A exportação assíncrona carrega os dados exportados para o armazenamento em nuvem do Google. Quando iniciado, você receberá um ID de trabalho de volta. Quando o trabalho for concluído, você poderá baixar os dados exportados.
A maioria dos parâmetros da exportação síncrona também funciona com a exportação assíncrona!
curl https://api.dev.entur.io/stop-places/v1/netex/export/initiate
Dica profissional: canalize a saída de curl para xmllint para formatar a saída:
curl https://api.dev.entur.io/stop-places/v1/netex/export/initiate | xmllint --format -
curl https://api.dev.entur.io/stop-places/v1/netex/export
curl https://api.dev.entur.io/stop-places/v1/netex/export/130116/content | zcat | xmllint --format - > export.xml
Veja também https://rutebanken.atlassian.net/browse/NRP-924
Limpe os dados existentes no postgresql (simplifique se for usado com frequência):
TRUNCATE stop_place CASCADE;
TRUNCATE quay CASCADE;
TRUNCATE topographic_place CASCADE;
Se você estiver executando isso em spring:run
, precisará ter certeza de que possui memória suficiente disponível para o processo java (no caso de grandes conjuntos de dados). Outro problema é o tamanho da pilha de threads, que pode precisar ser aumentado ao lidar com importações NeTEx realmente grandes. Exemplo:
export MAVEN_OPTS='-Xms256m -Xmx1712m -Xss256m -XX:NewSize=64m -XX:MaxNewSize=128m -Dfile.encoding=UTF-8'
Este arquivo NeTEx não deve conter ID NSR. (O prefixo NSR é configurável na classe ValidPrefixList)
Tiamat retornará a estrutura NeTEx modificada com seus próprios IDs NSR. Os IDs originais estarão presentes na lista de valores-chave de cada objeto.
curl -XPOST -H"Content-Type: application/xml" [email protected] http://localhost:1997/services/stop_places/netex
Ao importar com importType=INITIAL , um fluxo paralelo será criado, gerando o processo original. Durante a importação, as autorizações do usuário são verificadas, acessando assim o SecurityContextHolder. Por padrão, SecurityContextHolder usa DEFAULT_LOCAL_STRATEGY. Ao usar INITIAL importType, você deve dizer ao Spring para usar MODE_INHERITABLETHREADLOCAL para SecurityContextHolder, permitindo que o Spring duplique o contexto de segurança em threads gerados. Isso pode ser feito definindo a variável env:
-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
Caso contrário, o aplicativo poderá reclamar sobre o usuário não estar autenticado se o Spring tentar verificar a autorização em um processo gerado
O endpoint GraphQL está disponível em
https://api.dev.entur.io/stop-places/v1/graphql
Dica: UI GraphiQL disponível em https://api.dev.entur.io/graphql-explorer/stop-places usando GraphiQL : https://github.com/graphql/graphiql (use, por exemplo, Modify Headers
for Chrome para adicionar bearer- token para mutações)
Para criar o banco de dados para tiamat, baixe e use a ferramenta de linha de comando flyway: https://flywaydb.org/documentation/commandline/
As migrações são executadas quando o tiamat é iniciado.
Crie um novo arquivo de acordo com a documentação do flyway na pasta resources/db/migrations
. Confirme a migração junto com as alterações de código que exigem essa alteração de esquema. Siga a convenção de nomenclatura.
Várias consultas e scripts relacionados ao tiamat foram coletados aqui: https://github.com/entur/tiamat-scripts
Tiamat é construído usando CircleCI. Veja a pasta .circleci.