Use streaming parser in schedules

This commit is contained in:
Kacper Donat 2020-01-11 13:05:32 +01:00
parent 5fb80224ce
commit f64855e454
23 changed files with 368 additions and 103 deletions

View File

@ -13,5 +13,5 @@ APP_SECRET=1bdf86cdc78fba654e4f2c309c6bbdbd
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url # Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
# Configure your db driver and server_version in config/packages/doctrine.yaml # Configure your db driver and server_version in config/packages/doctrine.yaml
DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db" DATABASE_URL=sqlite:///%kernel.project_dir%/var/app.db
###< doctrine/doctrine-bundle ### ###< doctrine/doctrine-bundle ###

View File

@ -7,6 +7,7 @@
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"ext-json": "*", "ext-json": "*",
"cerbero/json-objects": "^1.1",
"doctrine/doctrine-cache-bundle": "^1.4", "doctrine/doctrine-cache-bundle": "^1.4",
"jms/serializer-bundle": "^3.5", "jms/serializer-bundle": "^3.5",
"nelmio/api-doc-bundle": "^3.5", "nelmio/api-doc-bundle": "^3.5",

178
composer.lock generated
View File

@ -4,8 +4,66 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "ea09297f32ae7bb1a4392cb514b0d0b2", "content-hash": "8efb4e4271b8598760e37b9b33d9a14f",
"packages": [ "packages": [
{
"name": "cerbero/json-objects",
"version": "v1.1.2",
"source": {
"type": "git",
"url": "https://github.com/cerbero90/json-objects.git",
"reference": "21eac219bb20ca80318fec88821217d7417ee09a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cerbero90/json-objects/zipball/21eac219bb20ca80318fec88821217d7417ee09a",
"reference": "21eac219bb20ca80318fec88821217d7417ee09a",
"shasum": ""
},
"require": {
"php": "~7.1",
"psr/http-message": "^1.0",
"salsify/json-streaming-parser": "^8.0"
},
"require-dev": {
"mockery/mockery": "^1.2",
"phpunit/phpunit": ">=7.0",
"squizlabs/php_codesniffer": "^3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Cerbero\\JsonObjects\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Andrea Marco Sartori",
"email": "andrea.marco.sartori@gmail.com",
"homepage": "https://github.com/cerbero90",
"role": "Developer"
}
],
"description": "Extract objects from large JSON files, endpoints or streams while saving memory.",
"homepage": "https://github.com/cerbero90/json-objects",
"keywords": [
"cerbero",
"json",
"json-objects",
"parser",
"stream"
],
"time": "2019-04-26T13:04:36+00:00"
},
{ {
"name": "doctrine/annotations", "name": "doctrine/annotations",
"version": "v1.8.0", "version": "v1.8.0",
@ -2964,6 +3022,56 @@
], ],
"time": "2017-02-14T16:28:37+00:00" "time": "2017-02-14T16:28:37+00:00"
}, },
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{ {
"name": "psr/log", "name": "psr/log",
"version": "1.1.2", "version": "1.1.2",
@ -3011,6 +3119,74 @@
], ],
"time": "2019-11-01T11:05:21+00:00" "time": "2019-11-01T11:05:21+00:00"
}, },
{
"name": "salsify/json-streaming-parser",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/salsify/jsonstreamingparser.git",
"reference": "0e5b5cb12611fe5376af653b360e12e8c6c6f3bd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/salsify/jsonstreamingparser/zipball/0e5b5cb12611fe5376af653b360e12e8c6c6f3bd",
"reference": "0e5b5cb12611fe5376af653b360e12e8c6c6f3bd",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-mbstring": "*",
"php": "^7.1"
},
"require-dev": {
"ext-json": "*",
"satooshi/php-coveralls": "~2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "8.0-dev"
}
},
"autoload": {
"psr-4": {
"JsonStreamingParser\\": "src",
"JsonStreamingParser\\Test\\": "tests"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Rob Gonzalez",
"email": "rob@salsify.com",
"homepage": "http://salsify.com/"
},
{
"name": "Maxim Gnatenko",
"email": "mgnatenko@gmail.com"
},
{
"name": "Max Grigorian",
"email": "maxakawizard@gmail.com",
"homepage": "http://wizardcat.com/"
},
{
"name": "ThePanz",
"email": "thepanz@gmail.com"
}
],
"description": "A streaming parser for JSON in PHP.",
"homepage": "https://github.com/salsify/jsonstreamingparser",
"keywords": [
"json",
"parser",
"streaming"
],
"time": "2019-10-13T13:40:17+00:00"
},
{ {
"name": "sensio/framework-extra-bundle", "name": "sensio/framework-extra-bundle",
"version": "v5.5.3", "version": "v5.5.3",

View File

@ -5,8 +5,8 @@ doctrine:
dbal: dbal:
driver: 'pdo_sqlite' driver: 'pdo_sqlite'
url: '%env(resolve:DATABASE_URL)%' url: '%env(resolve:DATABASE_URL)%'
logging: false logging: true
profiling: false profiling: true
orm: orm:
auto_generate_proxy_classes: '%kernel.debug%' auto_generate_proxy_classes: '%kernel.debug%'

View File

@ -1,4 +1,4 @@
version: '3' version: '2'
services: services:
nginx: nginx:
@ -11,6 +11,9 @@ services:
php: php:
build: docker/php build: docker/php
mem_limit: 2g
env_file:
- ./docker/php/.env
volumes: volumes:
- ./:/var/www:cached - ./:/var/www:cached
- ./docker/php/log.conf:/usr/local/etc/php-fpm.d/zz-log.conf - ./docker/php/log.conf:/usr/local/etc/php-fpm.d/zz-log.conf

2
docker/php/.env Normal file
View File

@ -0,0 +1,2 @@
XDEBUG_CONFIG=remote_host=172.17.0.1 remote_port=9001
PHP_IDE_CONFIG=serverName=czydojade

View File

@ -7,6 +7,8 @@ RUN docker-php-ext-install zip
RUN pecl install xdebug-2.9.0 && docker-php-ext-enable xdebug RUN pecl install xdebug-2.9.0 && docker-php-ext-enable xdebug
RUN echo "xdebug.remote_enable = 1" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini;
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');" RUN php -r "unlink('composer-setup.php');"
@ -16,3 +18,5 @@ RUN chmod +x /usr/local/bin/composer
RUN ln -snf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime RUN ln -snf /usr/share/zoneinfo/Europe/Warsaw /etc/localtime
WORKDIR /var/www WORKDIR /var/www
EXPOSE 9001

View File

@ -7,14 +7,15 @@
</div> </div>
<div class="departure__time"> <div class="departure__time">
<span class="departure__scheduled" v-if="departure.scheduled.format('HH:mm') !== departure.estimated.format('HH:mm')"> <fa :icon="['far', 'clock']" v-if="!departure.estimated" title="Czas rozkładowy, nie uwzględniający aktualnej sytuacji komunikacyjnej."/>
<span :class="[ 'departure__scheduled', departure.estimated && departure.scheduled.format('HH:mm') !== departure.estimated.format('HH:mm') && 'departure__scheduled--delayed']">
{{ departure.scheduled.format('HH:mm') }} {{ departure.scheduled.format('HH:mm') }}
</span> </span>
<span class="badge" :class="[departure.delay < 0 ? 'badge-danger' : 'badge-warning']" <span class="badge" :class="[departure.delay < 0 ? 'badge-danger' : 'badge-warning']"
v-if="departure.delay < 0 || departure.delay > 30"> v-if="departure.delay < 0 || departure.delay > 30">
{{ departure.delay|signed }}s {{ departure.delay|signed }}s
</span> </span>
<span class="departure__estimated">{{ departure.estimated.format('HH:mm') }}</span> <span class="departure__estimated" v-if="departure.estimated && departure.scheduled.format('HH:mm') !== departure.estimated.format('HH:mm')">{{ departure.estimated.format('HH:mm') }}</span>
</div> </div>
<div class="departure__stop"> <div class="departure__stop">

View File

@ -24,7 +24,7 @@
width: 9rem; width: 9rem;
text-align: right; text-align: right;
.departure__scheduled { .departure__scheduled--delayed {
text-decoration: line-through; text-decoration: line-through;
} }
} }

View File

@ -5,7 +5,7 @@ import { Moment } from "moment";
export interface Departure { export interface Departure {
display: string; display: string;
estimated: Moment; estimated: Moment;
scheduled: Moment; scheduled?: Moment;
stop: Stop; stop: Stop;
line: Line; line: Line;
delay: number; delay: number;

View File

@ -45,7 +45,7 @@ export const departures: Module<DeparturesState, RootState> = {
const departures = await response.json() as Jsonified<Departure>[]; const departures = await response.json() as Jsonified<Departure>[];
commit('update', departures.map(departure => { commit('update', departures.map(departure => {
departure.scheduled = moment.parseZone(departure.scheduled); departure.scheduled = moment.parseZone(departure.scheduled);
departure.estimated = moment.parseZone(departure.estimated); departure.estimated = departure.estimated && moment.parseZone(departure.estimated);
return departure as Departure; return departure as Departure;
})); }));

View File

@ -61,7 +61,8 @@ class DeparturesController extends Controller
*/ */
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request) public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
{ {
$stops = $stops->getManyById($request->query->get('stop')) $stops = $stops
->getManyById($request->query->get('stop'))
->flatMap([ $departures, 'getForStop' ]) ->flatMap([ $departures, 'getForStop' ])
->sortBy(function (Departure $departure) { ->sortBy(function (Departure $departure) {
return $departure->getEstimated(); return $departure->getEstimated();

View File

@ -38,15 +38,14 @@ class TrackEntity implements Entity, Fillable
* *
* @var LineEntity * @var LineEntity
* *
* @ORM\ManyToOne(targetEntity=LineEntity::class, fetch="EAGER") * @ORM\ManyToOne(targetEntity=LineEntity::class, fetch="EAGER", inversedBy="tracks")
*/ */
private $line; private $line;
/** /**
* Stops in track * Stops in track
* @var Collection * @var Collection
* @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="EXTRA_LAZY", mappedBy="track", cascade={"persist"}) * @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="LAZY", mappedBy="track", cascade={"persist"})
* @ORM\OrderBy({"order": "ASC"})
*/ */
private $stopsInTrack; private $stopsInTrack;

View File

@ -8,6 +8,7 @@ use App\Model\Trip;
use App\Service\IdUtils; use App\Service\IdUtils;
use Carbon\Carbon; use Carbon\Carbon;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Tests\Fixtures\Discriminator\Car;
/** /**
* @ORM\Entity * @ORM\Entity
@ -26,7 +27,7 @@ class TripStopEntity implements Fillable
/** /**
* @var TripEntity * @var TripEntity
* @ORM\ManyToOne(targetEntity=TripEntity::class, fetch="EAGER") * @ORM\ManyToOne(targetEntity=TripEntity::class, fetch="EAGER", inversedBy="stops")
* @ORM\Id * @ORM\Id
*/ */
private $trip; private $trip;
@ -98,7 +99,7 @@ class TripStopEntity implements Fillable
public function getDeparture(): Carbon public function getDeparture(): Carbon
{ {
return $this->departure; return Carbon::instance($this->departure);
} }
public function setDeparture(Carbon $departure): void public function setDeparture(Carbon $departure): void

View File

@ -3,31 +3,66 @@
namespace App\Provider\Database; namespace App\Provider\Database;
use App\Entity\StopEntity; use App\Entity\StopEntity;
use App\Entity\StopInTrack;
use App\Entity\TrackEntity;
use App\Entity\TripStopEntity; use App\Entity\TripStopEntity;
use App\Model\Departure;
use App\Model\Line;
use App\Model\Stop; use App\Model\Stop;
use App\Model\Vehicle;
use App\Provider\ScheduleRepository;
use Carbon\Carbon;
use Tightenco\Collect\Support\Collection;
use function Kadet\Functional\ref; use function Kadet\Functional\ref;
class GenericScheduleRepository extends DatabaseRepository class GenericScheduleRepository extends DatabaseRepository implements ScheduleRepository
{
const DEFAULT_DEPARTURES_COUNT = 8;
public function getDeparturesForStop(Stop $stop, \DateTime $from, int $count = 8)
{ {
public function getDeparturesForStop(
Stop $stop,
\DateTime $from,
int $count = ScheduleRepository::DEFAULT_DEPARTURES_COUNT
): Collection {
$query = $this->em $query = $this->em
->createQueryBuilder() ->createQueryBuilder()
->select('s') ->select('ts', 't')
->from(TripStopEntity::class, 's') ->from(TripStopEntity::class, 'ts')
->where('s.arrival >= :from') ->where('ts.departure >= :from')
->andWhere('s.stop = :stop') ->andWhere('ts.stop = :stop')
->join('ts.trip', 't')
->orderBy('ts.departure', 'ASC')
->setMaxResults($count) ->setMaxResults($count)
->getQuery() ->getQuery();
;
$schedule = collect($query->execute([ $schedule = collect($query->execute([
'from' => $from, 'from' => $from,
'stop' => $this->reference(StopEntity::class, $stop), 'stop' => $this->reference(StopEntity::class, $stop),
])); ]));
return $schedule->map(ref([$this, 'convert'])); $this->em->createQueryBuilder()
->select('t', 's', 'st')
->from(TrackEntity::class, 't')
->join('t.stopsInTrack', 's')
->join('s.stop', 'st')
->where('t.id in (:tracks)')
->orderBy('s.order', 'DESC')
->getQuery()
->execute([
':tracks' => $schedule->map(function (TripStopEntity $stop) {
return $stop->getTrip()->getTrack()->getId();
})->all()
]);
return $schedule->map(function (TripStopEntity $entity) use ($stop) {
$line = $entity->getTrip()->getTrack()->getLine();
/** @var StopEntity $last */
$last = $entity->getTrip()->getTrack()->getStopsInTrack()->last()->getStop();
return Departure::createFromArray([
'scheduled' => $entity->getDeparture(),
'stop' => $stop,
'display' => $last->getName(),
'line' => $this->convert($line),
]);
});
} }
} }

View File

@ -0,0 +1,17 @@
<?php
namespace App\Provider;
use App\Model\Stop;
use Tightenco\Collect\Support\Collection;
interface ScheduleRepository
{
const DEFAULT_DEPARTURES_COUNT = 8;
public function getDeparturesForStop(
Stop $stop,
\DateTime $from,
int $count = ScheduleRepository::DEFAULT_DEPARTURES_COUNT
): Collection;
}

View File

@ -16,6 +16,7 @@ use App\Model\Location;
use App\Service\DataUpdater; use App\Service\DataUpdater;
use App\Service\IdUtils; use App\Service\IdUtils;
use Carbon\Carbon; use Carbon\Carbon;
use Cerbero\JsonObjects\JsonObjects;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Helper\ProgressBar;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -24,6 +25,7 @@ use Symfony\Component\Console\Output\ConsoleSectionOutput;
use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Tightenco\Collect\Support\Collection; use Tightenco\Collect\Support\Collection;
use function Cerbero\JsonObjects\JsonObjects;
use function Kadet\Functional\ref; use function Kadet\Functional\ref;
class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
@ -63,6 +65,8 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
public function update(DataUpdateEvent $event) public function update(DataUpdateEvent $event)
{ {
$output = $event->getOutput();
$provider = ProviderEntity::createFromArray([ $provider = ProviderEntity::createFromArray([
'name' => $this->provider->getName(), 'name' => $this->provider->getName(),
'class' => ZtmGdanskProvider::class, 'class' => ZtmGdanskProvider::class,
@ -76,8 +80,13 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
$this->getOperators($provider, $event)->each($save); $this->getOperators($provider, $event)->each($save);
$this->getStops($provider, $event)->each($save); $this->getStops($provider, $event)->each($save);
$this->getTracks($provider, $event)->each($save); $this->getTracks($provider, $event)->each($save);
$lines = $this->getLines($provider, $event)->each($save); $lines = $this->getLines($provider, $event)->each($save);
$output->write('Flushing all things into database...');
$this->em->flush();
$this->em->clear();
$output->writeln('done');
$this->updateSchedule($provider, $lines, $event); $this->updateSchedule($provider, $lines, $event);
} }
@ -144,12 +153,16 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
$output->writeln(sprintf('done (%d)', count($stops))); $output->writeln(sprintf('done (%d)', count($stops)));
$this->logger->debug(sprintf("Saving %d stops tracks from ZTM Gdańsk.", count($stops))); $this->logger->debug(sprintf("Saving %d stops tracks from ZTM Gdańsk.", count($stops)));
return collect($stops)->map(function ($stop) use ($provider) { return collect($stops)
->filter(function ($stop) {
return $stop['nonpassenger'] !== null && $stop['nonpassenger'] !== 1;
})
->map(function ($stop) use ($provider) {
return StopEntity::createFromArray([ return StopEntity::createFromArray([
'id' => $this->ids->generate($provider, $stop['stopId']), 'id' => $this->ids->generate($provider, $stop['stopId']),
'name' => trim($stop['stopName'] ?? $stop['stopDesc']), 'name' => trim($stop['stopName'] ?? $stop['stopDesc']),
'variant' => trim($stop['zoneName'] == 'Gdańsk' ? $stop['stopCode'] : null), 'variant' => trim($stop['zoneName'] == 'Gdańsk' ? $stop['stopCode'] : null),
'latitude' => Location::fromArray($stop['stopLat']), 'latitude' => $stop['stopLat'],
'longitude' => $stop['stopLon'], 'longitude' => $stop['stopLon'],
'onDemand' => (bool)$stop['onDemand'], 'onDemand' => (bool)$stop['onDemand'],
'provider' => $provider, 'provider' => $provider,
@ -157,7 +170,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
}); });
} }
public function getTracks(ProviderEntity $provider, DataUpdateEvent $event) public function getTracks(ProviderEntity $provider, DataUpdateEvent $event, $stops = [])
{ {
ini_set('memory_limit', '2G'); ini_set('memory_limit', '2G');
@ -215,32 +228,29 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
'routeId' => $this->ids->of($line), 'routeId' => $this->ids->of($line),
])); ]));
$schedule = file_get_contents($url); $schedule = JsonObjects::from($url, 'stopTimes.*');
$schedule = json_decode($schedule, true)['stopTimes']; $trips = new Collection();
$schedule = collect($schedule)->groupBy(function ($stop) {
return sprintf("%s-%d", $stop['busServiceName'], $stop['order']);
});
collect($schedule)->map(function (Collection $trips, $id) use ($provider) { $schedule->each(function ($stop) use ($provider, &$trips) {
$entity = TripEntity::createFromArray([ $id = sprintf('%s-%d', $stop['busServiceName'], $stop['order']);
$trip = $trips[$id] ?? $trips[$id] = (function () use ($stop, $id, $provider) {
$trip = TripEntity::createFromArray([
'id' => $this->ids->generate($provider, $id), 'id' => $this->ids->generate($provider, $id),
'operator' => $this->em->getReference( 'operator' => $this->em->getReference(
OperatorEntity::class, OperatorEntity::class,
$this->ids->generate($provider, $trips->first()['agencyId']) $this->ids->generate($provider, $stop['agencyId'])
), ),
'track' => $this->em->getReference( 'track' => $this->em->getReference(
TrackEntity::class, TrackEntity::class,
$this->ids->generate($provider, $trips->first()['tripId']) $this->ids->generate($provider, sprintf('R%sT%s', $stop['routeId'], $stop['tripId']))
), ),
'variant' => $trips->first(function ($trip) {
return !empty($trip['noteSymbol']);
}, ['noteSymbol' => null])['noteSymbol'],
'note' => $trips->first(function ($trip) {
return !empty($trip['noteSymbol']);
}, ['noteDescription' => null])['noteDescription'],
]); ]);
$stops = $trips->map(function ($stop) use ($entity, $provider) { $this->em->persist($trip);
return $trip;
})();
$base = Carbon::create(1899, 12, 30, 00, 00, 00); $base = Carbon::create(1899, 12, 30, 00, 00, 00);
$date = Carbon::createFromFormat('Y-m-d', $stop['date'])->setTime(00, 00, 00); $date = Carbon::createFromFormat('Y-m-d', $stop['date'])->setTime(00, 00, 00);
@ -250,8 +260,8 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
$arrival = (clone $date)->add($arrival); $arrival = (clone $date)->add($arrival);
$departure = (clone $date)->add($departure); $departure = (clone $date)->add($departure);
return TripStopEntity::createFromArray([ $entity = TripStopEntity::createFromArray([
'trip' => $entity, 'trip' => $trip,
'stop' => $this->em->getReference( 'stop' => $this->em->getReference(
StopEntity::class, StopEntity::class,
$this->ids->generate($provider, $stop['stopId']) $this->ids->generate($provider, $stop['stopId'])
@ -260,17 +270,17 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
'arrival' => $arrival, 'arrival' => $arrival,
'departure' => $departure, 'departure' => $departure,
]); ]);
$entity->setTrip($trip);
$this->em->persist($entity);
}); });
$entity->setStops($stops);
return $entity;
})->each(ref([$this->em, 'persist']));
$this->logger->debug(sprintf('Got schedule for line %s from ZTM Gdańsk', $line->getId())); $this->logger->debug(sprintf('Got schedule for line %s from ZTM Gdańsk', $line->getId()));
$this->em->flush(); $this->em->flush();
$this->em->clear(); $this->em->clear();
gc_collect_cycles();
} }
public static function getSubscribedEvents() public static function getSubscribedEvents()
@ -296,7 +306,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
} }
$progress->finish(); $progress->finish();
$progress-> $event->getOutput()->writeln("");
$event->getOutput()->writeln("done"); $event->getOutput()->writeln("done");
} }
} }

View File

@ -9,6 +9,7 @@ use App\Model\Vehicle;
use App\Provider\Database\GenericScheduleRepository; use App\Provider\Database\GenericScheduleRepository;
use App\Provider\DepartureRepository; use App\Provider\DepartureRepository;
use App\Provider\LineRepository; use App\Provider\LineRepository;
use App\Provider\ScheduleRepository;
use App\Service\Proxy\ReferenceFactory; use App\Service\Proxy\ReferenceFactory;
use Carbon\Carbon; use Carbon\Carbon;
use Tightenco\Collect\Support\Collection; use Tightenco\Collect\Support\Collection;
@ -24,13 +25,17 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
/** @var ReferenceFactory */ /** @var ReferenceFactory */
private $reference; private $reference;
/** @var ScheduleRepository */
private $schedule;
/** /**
* @param LineRepository $lines * @param LineRepository $lines
*/ */
public function __construct(LineRepository $lines, ReferenceFactory $reference) public function __construct(LineRepository $lines, ScheduleRepository $schedule, ReferenceFactory $reference)
{ {
$this->lines = $lines; $this->lines = $lines;
$this->reference = $reference; $this->reference = $reference;
$this->schedule = $schedule;
} }
public function getForStop(Stop $stop): Collection public function getForStop(Stop $stop): Collection

View File

@ -12,6 +12,7 @@ use App\Provider\DepartureRepository;
use App\Provider\LineRepository; use App\Provider\LineRepository;
use App\Provider\MessageRepository; use App\Provider\MessageRepository;
use App\Provider\Provider; use App\Provider\Provider;
use App\Provider\ScheduleRepository;
use App\Provider\StopRepository; use App\Provider\StopRepository;
use App\Provider\TrackRepository; use App\Provider\TrackRepository;
use App\Provider\ZtmGdansk\{ZtmGdanskDepartureRepository, ZtmGdanskMessageRepository}; use App\Provider\ZtmGdansk\{ZtmGdanskDepartureRepository, ZtmGdanskMessageRepository};
@ -67,7 +68,7 @@ class ZtmGdanskProvider implements Provider
$schedule = $schedule->withProvider($provider); $schedule = $schedule->withProvider($provider);
$this->lines = $lines; $this->lines = $lines;
$this->departures = new ZtmGdanskDepartureRepository($lines, $referenceFactory); $this->departures = new ZtmGdanskDepartureRepository($lines, $schedule, $referenceFactory);
$this->stops = $stops; $this->stops = $stops;
$this->messages = $messages; $this->messages = $messages;
$this->tracks = $tracks; $this->tracks = $tracks;

View File

@ -35,7 +35,7 @@ class DataUpdater
$connection->getConfiguration()->setSQLLogger(null); $connection->getConfiguration()->setSQLLogger(null);
$schema = $connection->getSchemaManager(); $schema = $connection->getSchemaManager();
$path = $connection->getParams()['path']; $path = preg_replace("~sqlite:///~si", '', $connection->getParams()['path']);
$backup = "$path.backup"; $backup = "$path.backup";
copy($path, $backup); copy($path, $backup);

View File

@ -1,4 +1,7 @@
{ {
"cerbero/json-objects": {
"version": "v1.1.2"
},
"doctrine/annotations": { "doctrine/annotations": {
"version": "1.0", "version": "1.0",
"recipe": { "recipe": {
@ -175,12 +178,18 @@
"psr/container": { "psr/container": {
"version": "1.0.0" "version": "1.0.0"
}, },
"psr/http-message": {
"version": "1.0.1"
},
"psr/log": { "psr/log": {
"version": "1.0.2" "version": "1.0.2"
}, },
"psr/simple-cache": { "psr/simple-cache": {
"version": "1.0.1" "version": "1.0.1"
}, },
"salsify/json-streaming-parser": {
"version": "v8.1.0"
},
"sensio/framework-extra-bundle": { "sensio/framework-extra-bundle": {
"version": "5.2", "version": "5.2",
"recipe": { "recipe": {