Skip to content

Add lost property to vehicles #32

@faultyserver

Description

@faultyserver

In the course of an agency's operation, there may be times where a Vehicle is taken out of commission while it is traveling on a Route. I've had a personal experience where a bus caught fire and was unable to continue it's trip. As one of 2 buses on the 25 minute loop, this caused major delays for the route, but was completely ignored by existing transit applications at the time.

Most applications continued reporting the original scheduled stop times for the route (even though the bus that would make those stops was not in service), while others just showed increasing wait times for the bus.

The idea of the lost property of a Vehicle is an attempt to automatically determine situations like these and inform users of major delays as early as possible (rather than just accumulating wait times).

The implementation of this property will be through a Middleware class that adds it to the Vehicle model. The Middleware will also add a hidden last_moved_at property to preserve state through multiple update cycles. On every cycle where the latitude or longitude of the Vehicle changes, last_moved_at will be updated to Time.now. If last_moved_at exceeds a configurable threshold, then lost will be set to true for the Vehicle.

When the lost property is true, the Middleware will not proxy events for that vehicle up the rest of the stack. The Middleware will, however, send a lost event up the stack so that clients can respond accordingly. This middleware should come closely after the Agency in the stack to avoid any miscellaneous events relating to the Vehicle coming from other Middlewares.

Once the position of a Vehicle changes again, it's lost property will be set to false and normal proxying will resume.

Here's a quick implementation of the Middleware:

class Runaway < Shark::Middleware # Names subject to change
  on_install do
    Shark::Vehicle.attribute :lost, default: false, nilable: false, required: false
    Shark::Vehicle.attribute :last_moved_at, default: ->{ Time.now }, nilable: true, required: false
  end

  on 'vehicles', :update  do |event|
    vehicle = event.args.first

    # If the vehicle moved in this cycle, update `last_moved_at`
    vehicle.last_moved_at = Time.now if vehicle.position_changed?

    # Only fire the `lost` event once after losing the vehicle.
    if vehicle.last_moved_at > configuration.threshold && !vehicle.lost?
      vehicle.lost = true
      fire(Shark::Event.new(
        topic: vehicle.identifier,
        type: :lost,
        args: [vehicle],
        kwargs: {},
        originator: vehicle.identifier
      ))
    else
      vehicle.lost = false
      # Potentially fire a `found` event
    end

    # Only proxy the original event if the vehicle is not currently lost.
    fire(event) unless vehicle.lost?
  end
end

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions