Internal API Documentation¶
These Python modules are only useful to you if you’re working directly on or with the MeteorPi server and database code.
Server: meteorpi_server¶
Logic to build the Flask based WSGI app, and optionally run it as a local Tornado based server for testing. The app is modular, initially not populated with any routes - these are provided by the xxx_api modules, allowing for modular assembly of an app with the functions you need for your application.
-
class
meteorpi_server.MeteorApp(db)[source]¶ Common functionality for MeteorPi WSGI apps. This won’t contain any routes by default, these must be added using the functionality in admin_api, importer_api, query_api etc. This allows you to customise your application to suit, rather than forcing all the functionality into every instance. It might be sensible, for example, to only import the query API for a node which will never need external administration or configuration.
Variables: app – A WSGI compliant application, this can be referenced from e.g. a fastcgi WSGI container and used to connect an external server such as LigHTTPD or Apache to the application logic. -
__init__(db)[source]¶ Create a new MeteorApp, setting up the internal DB
Parameters: db (MeteorDatabase) – An instance of meteorpi_fdb.MeteorDatabaseto use when accessing the data and file stores.
-
static
authentication_failure(message='Authorization required')[source]¶ Returns an authentication required response, including an optional message.
Parameters: message (string) – An optional message, can be used to specify additional information Returns: flask error code, can be used as a return type from service methods
-
static
not_found(entity_id=None, message='Entity not found')[source]¶ Build a response to indicate that the requested entity was not found.
Parameters: Returns: A flask Response object, can be used as a return type from service methods
-
requires_auth(roles=None)[source]¶ Used to impose auth constraints on requests which require a logged in user with particular roles.
Parameters: roles (list[string]) – A list of stringrepresenting roles the logged in user must have to perform this action. The user and password are passed in each request in the authorization header obtained from request.authorization, the user and password are checked against the user database and roles obtained. The user must match an existing user (including the password, obviously) and must have every role specified in this parameter.Returns: The result of the wrapped function if everything is okay, or a flask.abort(403) error code if authentication fails, either because the user isn’t properly authenticated or because the user doesn’t have the required role or roles.
-
-
class
meteorpi_server.MeteorServer(db_path, file_store_path, port, add_routes=True)[source]¶ Tornado based server, exposes an instance of
meteorpi_server.MeteorAppon localhost, can either be configured to expose all available APIs or can have such APIs added individually.The database and application are exposed as instance properties to aid testing.
Variables: - db (MeteorDatabase) – The db used for this server
- meteor_app (MeteorApp) – The application this server exposes
- server (HTTPServer) – The tornado HTTPServer instance
- port (int) – The port on which we’re listening for HTTP requests
-
class
IOLoopThread[source]¶ A thread used to run the Tornado IOLoop in a non-blocking fashion, mostly for testing
-
MeteorServer.__init__(db_path, file_store_path, port, add_routes=True)[source]¶ Create a new instance, does not start the server.
Parameters: - db_path (string) – Path to the database, i.e. ‘localhost:/var/lib/firebird/2.5/data/meteorpi.fdb’
- file_store_path (string) – File path to a directory on disk where the data store can store and retrieve its file data, i.e. path.expanduser(“~/meteorpi_files”)
- port (int) – Port on which the HTTP server should run
- add_routes (boolean) – Optional, defaults to True. If True then all routes from admin_api, importer_api and query_api will be added to the application, otherwise no routes will be added and you’ll have to do so explicitly.
-
static
MeteorServer.add_all_routes(meteor_app)[source]¶ Add routes from admin_api, importer_api and query_api to the specified application
Parameters: meteor_app (MeteorApp) – The application to which routes should be added
-
meteorpi_server.query_api.add_routes(meteor_app, url_path='')[source]¶ Adds search and retrieval routes to a
meteorpi_server.MeteorServerinstanceParameters: - meteor_app (MeteorApp) – The
meteorpi_server.MeteorAppto which routes should be added - url_path (string) – The base path used for the query routes, defaults to ‘’
- meteor_app (MeteorApp) – The
Also provides the import API - this is an extensible system which can be used to receive data from an export task on the database side. The code includes an implementation of this system which handles event and file record replication, but the system can also be used for other purposes such as social media gateways, notification etc.
-
class
meteorpi_server.importer_api.BaseImportReceiver[source]¶ Base class for entities which should be able to receive imports, whether that’s to handle database to database replication or otherwise. This base implementation is functional, but simply replies to both event and file record imports with ‘complete’ messages, thus never triggering either status imports or binary data.
-
static
get_importing_user_id()[source]¶ Retrieve the importing user ID from the request context, this user will have already authenticated correctly by the point the import receiver is called.
Returns: The string user_id for the importing user
-
receive_event(import_request)[source]¶ Handle an Event import
Parameters: import_request (ImportRequest) – An instance of meteorpi_server.importer_api.ImportRequestwhich contains the parsed request, including themeteorpi_model.Eventobject along with methods that can be used to continue the import process. The Event is available as import_request.entity.Returns: A Flask response, typically generated using the response_xxx() methods on the import_request. If no return is made or None is returned then treated as equivalent to returning response_complete() to terminate import of this Event
-
receive_file_data(file_id, file_data, md5_hex)[source]¶ Handle the reception of uploaded file data for a given ID. There is no return mechanism for this method, as the import protocol specifies that after a binary file is uploaded the corresponding file record or event should be sent again. This allows us to implement the import in a stateless fashion, caching aside, at the cost of an additional very small HTTP request. The request is small because all the exporter has to do, typically, is send the ID of the event or file record as the import infrastructure in this module caches the full record locally.
Parameters: - file_id (uuid.UUID) – The ID of the FileRecord for this file data
- file_data – A file upload response from Flask’s upload handler, acquired with file_data = request.files[‘file’]
- md5_hex – The hex representation of the MD5 hash of this file from the exporting party. This should be checked against the result of meteorpi_model.get_md5_hash(path) to ensure integrity of the file reception, and the file discarded or otherwise ignored if it does not match.
Returns: None, continues the import irrespective of whether the file was received or not.
-
receive_file_record(import_request)[source]¶ Handle a FileRecord import
Parameters: import_request (ImportRequest) – An instance of meteorpi_server.importer_api.ImportRequestwhich contains the parsed request, including themeteorpi_model.FileRecordobject along with methods that can be used to continue the import process. The FileRecord is available as import_request.entity.Returns: A Flask response, typically generated using the response_xxx() methods on the import_request. If no return is made or None is returned then treated as equivalent to returning response_complete() to terminate import of this FileRecord
-
receive_status(import_request)[source]¶ Handle a
meteorpi_model.CameraStatusimport in response to a previous return of response_need_status() from one of themeteorpi_model.Eventormeteorpi_model.FileRecordimport methods.Parameters: import_request (ImportRequest) – An instance of meteorpi_server.importer_api.ImportRequestwhich contains the parsed request, including themeteorpi_model.CameraStatusobject along with methods that can be used to continue the import process. The CameraStatus is available as import_request.entity.Returns: A Flask response, typically generated using the response_xxx() methods on the import_request. If no return is made or None is returned then treated as equivalent to returning response_continue() to return to the import of the enclosing entity. This is different to receive_file_record() and receive_event() because we only ever see a status imported in response to an attempt to import an event or file record which has a status we don’t have on the importing side.
-
static
-
class
meteorpi_server.importer_api.ImportRequest(entity, entity_id)[source]¶ Helper used when importing, makes use of the ‘cached_request’ request transparent to the importing party.
Variables: - entity_cache – LRU cache used to stash entities being imported.
- logger – Logs to ‘meteorpi.server.import’
- entity_type – The type of the ID being imported, which will be one of ‘file’, ‘status’, ‘event’ or ‘none’.
-
__init__(entity, entity_id)[source]¶ Constructor, don’t use this from your own code, instead use process_request() to create one from the Flask request context.
Parameters: - entity – The entity being imported, either pulled from the request directly or from the cache. This can be None under error conditions, in which case the only legitimate response is to send a ‘continue’ message back to the exporter, at which point it will re-send the necessary information to rebuild the cache.
- entity_id – The ID of the entity being imported, this will always be defined.
-
static
process_request()[source]¶ Retrieve a CameraStatus, Event or FileRecord from the request, based on the supplied type and ID. If the type is ‘cached_request’ then the ID must be specified in ‘cached_request_id’ - if this ID is not for an entity in the cache this method will return None and clear the cache (this should only happen under conditions where we’ve failed to correctly handle caching, such as a server restart or under extreme load, but will result in the server having to re-request a previous value from the exporting party).
Returns: A dict containing ‘entity’ - the entity for this request or None if there was an issue causing an unexpected cache miss, and ‘entity-id’ which will be the UUID of the entity requested. The entity corresponding to this request, or None if we had an issue and there was an unexpected cache miss.
-
response_complete()[source]¶ Signal that this particular entity has been fully processed. The exporter will not send it to this target again under this particular export configuration (there is no guarantee another export configuration on the same server won’t send it, or that it won’t be received from another server though, so you must always check whether you have an entity and return this status as early as possible if so)
Returns: A response that can be returned from a Flask service method
-
response_continue()[source]¶ Signals that a partial reception of data has occurred and that the exporter should continue to send data for this entity. This should also be used if import-side caching has missed, in which case the response will direct the exporter to re-send the full data for the entity (otherwise it will send back the entity ID and rely on the import party’s caching to resolve it). Use this for generic cases where we need to be messaged again about this entity - currently used after requesting and receiving a status block, and in its cache-refresh form if we have a cache miss during import.
Returns: A response that can be returned from a Flask service method
-
static
response_continue_after_file()[source]¶ As with response_continue, but static to allow it to be called from context where we don’t have a populated ImportRequest object. Always uses cached IDs, with the expectation that a subsequent request will force cache revalidation if required. Use this when acting on reception of binary data.
Returns: A response that can be returned from a Flask service method
-
static
response_failed(message='Import failed')[source]¶ Signal that import for this entity failed. Whether this results in a retry either immediately or later in time is entirely up to the exporting party - this should therefore only be used for error cases, and not used to indicate duplicate data (use the response_complete for this as it tells the exporter that it shouldn’t send the data again)
Parameters: message (string) – An optional message to convey about the failure Returns: A response that can be returned from a Flask service method
-
static
response_need_file_data(file_id)[source]¶ Signal the exporter that we need the binary data associated with a given file ID
Parameters: file_id (uuid.UUID) – the UUID of the meteorpi_model.FileRecordfor which we don’t currently have dataReturns: A response that can be returned from a Flask service method
-
class
meteorpi_server.importer_api.MeteorDatabaseImportReceiver(db)[source]¶ An implementation of
meteorpi_server.import_api.BaseImportReceiverthat connects to ameteorpi_fdb.MeteorDatabaseand pushes any data to it on import, including managing the acquisition of any additional information (camera status, binary file data) required in the process.
-
meteorpi_server.importer_api.add_routes(meteor_app, handler=None, url_path='/import')[source]¶ Add two routes to the specified instance of
meteorpi_server.MeteorAppto implement the import API and allow for replication of data to this server.Parameters: - meteor_app (meteorpi_server.MeteorApp) – The
meteorpi_server.MeteorAppto which import routes should be added - handler (meteorpi_server.importer_api.BaseImportReceiver) – A subclass of
meteorpi_server.importer_api.BaseImportReceiverwhich is used to handle the import. If not specified this defaults to an instance ofmeteorpi_server.importer_api.MeteorDatabaseImportReceiverwhich will replicate any missing information from the import into the database attached to the meteor_app. - url_path (string) – The base of the import routes for this application. Defaults to ‘/import’ - routes will be created at this path and as import_path/data/<id> for binary data reception. Both paths only respond to POST requests and require that the requests are authenticated and that the authenticated user has the ‘import’ role.
- meteor_app (meteorpi_server.MeteorApp) – The
Database: meteorpi_fdb¶
Firebird based data access layer, uses a simple directory based file store to handle file data. The database itself provides for search, retrieval and registration operations, with extra modules providing export mark and process functionality. Caching is implemented as an in-memory LRU cache for each main event type, mostly to optimise the kind of burst access we tend to have during imports and exports, and during pagination of searches.
-
class
meteorpi_fdb.MeteorDatabase(db_path, file_store_path, db_user='meteorpi', db_password='meteorpi', installation_id=None)[source]¶ Class representing a single MeteorPi relational database and file store.
Variables: - con – Database connection used to access the db
- db_path – Path to the database
- file_store_path – Path to the file store on disk
- generators – Helper object containing generator functions to retrieve entities lazily
- installation_id (string) – The installation ID, either supplied explicitly in the constructor or derived automatically from the network interface MAC address (used if None is passed to the constructor for this property)
-
__init__(db_path, file_store_path, db_user='meteorpi', db_password='meteorpi', installation_id=None)[source]¶ Create a new db instance. This connects to the specified firebird database and retains a connection which is then used by methods in this class when querying or updating the database.
Parameters: - db_path (string) – String passed to the firebird database driver and specifying a file location. Defaults to
- file_store_path (string) – File data is stored on the file system in a flat structure within the specified directory. If this location doesn’t exist it will be created, along with any necessary parent directories.
- db_user (string) – User for the database, defaults to ‘meteorpi’
- db_password (string) – Password for the database, defaults to ‘meteorpi’
- installation_id (string) – 12 Character string containing the installation ID which will be used as the default when registering new files and events to this database. If set to none this will default to an attempt to calculate the ID from the MAC address of the first network interface found.
-
clear_database()[source]¶ Delete ALL THE THINGS!
This doesn’t reset any internal counters used to generate IDs but does otherwise remove all data from the database. Also purges all files from the fileStore
-
create_or_update_export_configuration(export_config)[source]¶ Create a new file export configuration or update an existing one
Parameters: export_config (ExportConfiguration) – a meteorpi_model.ExportConfigurationcontaining the specification for the export. If this doesn’t include a ‘config_id’ field it will be inserted as a new record in the database and the field will be populated, updating the supplied object. If it does exist already this will update the other properties in the database to match the supplied object.Returns: The supplied meteorpi_model.ExportConfigurationas stored in the DB. This is guaranteed to have its ‘config_id’uuid.UUIDfield defined.
-
create_or_update_user(user_id, password, roles)[source]¶ Create a new user record, or update an existing one
Parameters: - user_id – user ID to update or create
- password – new password, or None to leave unchanged
- roles – new roles, or None to leave unchanged
Returns: the action taken, one of “none”, “update”, “create”
Raises: ValueError if there is no existing user and either password or roles is None
-
defer_export_tasks(config_id, seconds)[source]¶ Increment the export time of all events for a given config such that the earliest is seconds into the future
Parameters: - config_id (uuid.UUID) – The UUID of an export configuration
- seconds (int) – The number of seconds by which tasks associated with this export configuration should be delayed. Any tasks that would occur before (now + seconds) are instead marked to occur at exactly that time. Tasks which were scheduled for further in the future, or for other export configurations, are not changed.
-
delete_export_configuration(config_id)[source]¶ Delete a file export configuration by external UUID
Parameters: config_id (uuid.UUID) – the ID of the config to delete
-
delete_user(user_id)[source]¶ Completely remove the specified user ID from the system
Parameters: user_id (string) – The user_id to remove
-
file_path_for_id(file_id)[source]¶ Get the system file path for a given file ID. Does not guarantee that the file exists!
Parameters: file_id (uuid.UUID) – ID of a file (which may or may not exist, this method doesn’t check) Returns: System file path for the file
-
get_camera_status(time=None, camera_id=None)[source]¶ Return the camera status for a given time, or None if no status is available.
Parameters: - time (datetime.datetime) – UTC time at which we want to know the camera status ID, defaults to model.now() if not specified
- camera_id (string) – The ID of the camera to query, defaults to the current installation ID if not specified
Returns: A
meteorpi_model.CameraStatusor None if no status was available
-
get_camera_status_by_id(status_id)[source]¶ Return the camera status block with the given UUID
Parameters: status_id (uuid.UUID) – UUID of the camera status Returns: An instance of meteorpi_model.CameraStatusor None if none matched.
-
get_cameras()[source]¶ Retrieve the IDs of all cameras with active status blocks. As the model has changed somewhat since this code was first written this in effect means the IDs of all cameras we’ve ever seen, as we no longer have a ‘valid_to’ entry in the status table.
Returns: A list of camera IDs for all cameras with status blocks
-
get_event(event_id)[source]¶ Retrieve an existing
meteorpi_model.Eventby its IDParameters: event_id (uuid.UUID) – UUID of the event Returns: A meteorpi_model.Eventinstance, or None if not found
-
get_export_configuration(config_id)[source]¶ Retrieve the ExportConfiguration with the given ID
Parameters: config_id (uuid.UUID) – ID for which to search Returns: a meteorpi_model.ExportConfigurationor None, or no match was found.
-
get_export_configurations()[source]¶ Retrieve all ExportConfigurations held in this db
Returns: a list of all meteorpi_model.ExportConfigurationon this server
-
get_file(file_id)[source]¶ Retrieve an existing
meteorpi_model.FileRecordby its IDParameters: file_id (uuid.UUID) – UUID of the file record Returns: A meteorpi_model.FileRecordinstance, or None if not found
-
get_high_water_mark(camera_id=None)[source]¶ Retrieves the high water mark for a given camera, defaulting to the current installation ID
Parameters: camera_id (string) – The camera ID to check for, or the default installation ID if not specified Returns: A UTC datetime for the high water mark, or None if none was found.
-
get_next_entity_to_export()[source]¶ Examines the t_fileExport and t_eventExport tables, finds the earliest incomplete export task and builds either a
meteorpi_fdb.FileExportTaskor ameteorpi_fdb.EventExportTaskas appropriate. These task objects can be used to retrieve the underlying entity and export configuration, and to update the completion state or push the timestamp into the future, deferring evaluation of the task until later. Only considers tasks where the timestamp is before (or equal to) the current time.Returns: Either None, if no exports are available, or a meteorpi_fdb.FileExportTaskormeteorpi_fdb.EventExportTaskdepending on whether a file or event is next in the queue to export.
-
get_user(*args, **kwds)[source]¶ Retrieve a user record
Parameters: - user_id – the user ID
- password – password
Returns: A
meteorpi_model.Userif everything is correctRaises: ValueError if the user is found but password is incorrect or if the user is not found.
-
get_users()[source]¶ Retrieve all users in the system
Returns: A list of meteorpi_model.User
-
has_event_id(event_id)[source]¶ Check for the presence of the given event_id
Parameters: event_id (uuid.UUID) – The event ID Returns: True if we have a meteorpi_model.Eventwith this ID, False otherwise
-
has_file_id(file_id)[source]¶ Check for the presence of the given file_id
Parameters: event_id (uuid.UUID) – The file ID Returns: True if we have a meteorpi_model.FileRecordwith this ID, False otherwise
-
has_status_id(status_id)[source]¶ Check for the presence of the given status_id
Parameters: status_id (uuid.UUID) – The camera status ID Returns: True if we have a meteorpi_model.CameraStatuswith this ID, False otherwise
-
import_camera_status(status)[source]¶ Import a new camera status block, used by the import server - do not use this for local status changes, it doesn’t update high water marks and will not execute any kind of roll-back. Clears the status cache, as camera status instances are somewhat dynamically generated based on other instances, most particularly for their time ranges.
Parameters: status – The new camera status block to import, this must be pre-populated with all required fields.
-
import_event(event, user_id)[source]¶ Functionality used by the import API, pulls in a
meteorpi_model.Eventincluding its pre-existing links to camera status and UUID. Do not use this to register a new event, it is only for use by the import system, this system ensures that all pre-requisites (files, camera status etc) are in place. If you use it outside of this context you will break your database. Don’t.Parameters: - event (Event) – The
meteorpi_model.Eventinstance to import - user_id (string) – The user_id of the importing
meteorpi_model.User
Internal: - event (Event) – The
-
import_file_record(file_record, user_id)[source]¶ Used by the import system to import a previously instantiated and named
meteorpi_model.FileRecord. Do not use this method outside of the import system, this system will ensure that any pre-requisite status or file data is in place, using this method directly will certainly break your database.Parameters: - file_record (FileRecord) – The
meteorpi_model.FileRecordto import - user_id (string) – The user_id of the importing
meteorpi_model.User
Returns: The integer internal ID of the imported record, used when importing events to create the link tables without additional database queries.
Internal: - file_record (FileRecord) – The
-
mark_entities_to_export(export_config)[source]¶ Apply the specified
meteorpi_model.ExportConfigurationto the database, running its contained query and creating rows in t_eventExport or t_fileExport for matching entities.Parameters: export_config (ExportConfiguration) – An instance of meteorpi_model.ExportConfigurationto apply.Returns: The integer number of rows added to the export tables
-
register_event(camera_id, event_time, event_type, file_records=None, event_meta=None)[source]¶ Register a new event, updating the database and returning the corresponding Event object
Parameters: - camera_id (string) – The ID of the camera which produced this event
- event_time (datetime) – The UTC datetime of the event
- event_type (NSString) – A
meteorpi_model.NSStringdescribing the semantic type of this event - file_records – A list of
meteorpi_model.FileRecordassociated with this event. These must already exist, typically multiple calls would be made to register_file() before registering the associated event - event_meta – A list of
meteorpi_model.Metaused to provide additional information about this event
Returns: The
meteorpi_model.Eventas stored in the database
-
register_file(file_path, mime_type, semantic_type, file_time, file_metas, camera_id=None, file_name=None)[source]¶ Register a file in the database, also moving the file into the file store. Returns the corresponding FileRecord object.
Parameters: - file_path (string) – The path of the file on disk to register. This file will be moved into the file store and renamed.
- mime_type (string) – MIME type of the file
- semantic_type (NSString) – A
meteorpi_model.NSStringdefining the semantic type of the file - file_time (datetime) – UTC datetime for the file
- file_metas (list[Meta]) – A list of
meteorpi_model.Metadescribing additional properties of the file - camera_id (string) – The camera ID which created this file. If not specified defaults to the current installation ID
- file_name (string) – An optional file name, primarily used to display in the UI and provide help when downloading.
Returns: The resultant
meteorpi_model.FileRecordas stored in the database
-
search_events(search)[source]¶ Search for
meteorpi_model.EvententitiesParameters: search – an instance of meteorpi_model.EventSearchused to constrain the events returned from the DBReturns: a structure of {count:int total rows of an unrestricted search, events:list of meteorpi_model.Event}
-
search_files(search)[source]¶ Search for
meteorpi_model.FileRecordentitiesParameters: search – an instance of meteorpi_model.FileRecordSearchused to constrain the events returned from the DBReturns: a structure of {count:int total rows of an unrestricted search, events:list of meteorpi_model.FileRecord}
-
set_high_water_mark(time, camera_id=None, allow_rollback=True, allow_advance=True)[source]¶ Sets the ‘high water mark’ for this installation.
This is the latest point before which all data has been processed, when this call is made any data products (events, images etc) with time stamps later than the high water mark will be removed from the database. Any camera status blocks with validFrom dates after the high water mark will be removed.
Internal:
-
update_camera_status(ns, time=None, camera_id=None)[source]¶ Update the status for a camera, optionally specify a time (defaults to model.now()).
If the time is earlier than the current high water mark for this camera any data products derived after that time will be deleted as if setHighWaterMark was called.
Clears the status cache.
Parameters: - ns (CameraStatus) – The new camera status. If an existing camera status is supplied (one with an assigned ID) the ID will be ignored and a new one generated, this makes it easier to update a camera status by retrieving it, modifying fields and then calling this method.
- time (datetime.datetime) – The time from which the new status should apply, defaults to now if not specified, should be a UTC time.
- camera_id (string) – The camera to which this status applies, or the default installation ID if not specified
-
class
meteorpi_fdb.exporter.EventExportTask(db, config_id, config_internal_id, event_id, event_internal_id, timestamp, status, target_url, target_user, target_password)[source]¶ Represents a single active Event export, providing methods to get the underlying
meteorpi_model.Event, themeteorpi_model.ExportConfigurationand to update the completion state in the database.
-
class
meteorpi_fdb.exporter.FileExportTask(db, config_id, config_internal_id, file_id, file_internal_id, timestamp, status, target_url, target_user, target_password)[source]¶ Represents a single active FileRecord export, providing methods to get the underlying
meteorpi_model.FileRecord, themeteorpi_model.ExportConfigurationand to update the completion state in the database.
-
class
meteorpi_fdb.exporter.MeteorExporter(db, mark_interval_seconds=300, max_failures_before_disable=4, defer_on_failure_seconds=1800, scheduler=None)[source]¶ Manages the communication part of MeteorPi’s export mechanism, acquiring
meteorpi_fdb.FileExportTaskandmeteorpi_fdb.EventExportTaskinstances from the database and sending them on to the appropriate receiver. This class in effect defines the communication protocol used by this process.The scheduler defined by default will also handle back-off under failure conditions. If an export fails, the count of failures (since the server was started) for that export config will be incremented and all export tasks for that config will be pushed a configurable distance into the future. If it fails more than a certain number of times the config will be marked as disabled. Any successful export will reset the failure count.
Variables: scheduler – An instance of apscheduler.schedulers.background.BackgroundSchedulerused to schedule regular mark of entities to export and trigger the actual export of such entities.-
class
ExportStateCache(export_task, state='not_started')[source]¶ Used as a continuation when processing a multi-stage export. On sub-task completion, if the export_task is set to None this is an indication that the task is completed (whether this means it’s failed or succeeded, there’s nothing left to do).
-
MeteorExporter.__init__(db, mark_interval_seconds=300, max_failures_before_disable=4, defer_on_failure_seconds=1800, scheduler=None)[source]¶ Build a new MeteorExporter. The export process won’t run by default, you must call the appropriate methods on this object to actually start exporting. A scheduler is created to handle automated, regular, exports, but is not started, you must explicitly call its start method if you want regular exports to function.
Parameters: - db (MeteorDatabase) – The database to read from, for both entities under replication and the export configurations.
- mark_interval_seconds (int) – The number of seconds after finishing on mark / export round that the next one will be triggered. Defaults to 300 for a five minute break. Note that at the end of an export round the process is re-run immediately, only finishing when there was nothing to do. This means that if we have a lot of data generated during an export run we won’t wait another five minutes before we process the new data.
- defer_on_failure_seconds (int) – The number of seconds into the future which will be applied to any tasks pending for a given config when a task created by that config fails (including the failed task). The timestamp for any tasks with timestamps less than now + defer_on_failure_seconds will be set to now + defer_on_failure_seconds.
- scheduler – The scheduler to use, defaults to a BackgroundScheduler with a non-daemon thread if not specified. Use a blocking one for test purposes.
- max_failures_before_disable (int) – The number of times an export configuration can have its exports fail before it is disabled.
-
MeteorExporter.handle_next_export()[source]¶ Retrieve and fully evaluate the next export task, including resolution of any sub-tasks requested by the import client such as requests for binary data, camera status etc.
Returns: An instance of ExportStateCache, the ‘state’ field contains the state of the export after running as many sub-tasks as required until completion or failure. If there were no jobs to run this returns None. complete: A job was processed and completed. The job has been marked as complete in the database continue: A job was processed, more information was requested and sent, but the job is still active failed: A job was processed but an error occurred during processing confused: A job was processed, but the importer returned a response which we couldn’t recognise
-
class
The core search operations are split into SQL generation in the sql_builder module, and lazy instantiation of the domain entities in the generators module. While most existing APIs in the main database then instantiate lists of results in response to search, if you are extending the server and need to iterate over all files or all events these generators allow you to do so in an efficient manner.
-
class
meteorpi_fdb.generators.MeteorDatabaseGenerators(db)[source]¶ Generator functions used to retrieve, and cache, items from the database.
-
cache_clear(cache)[source]¶ Clear a named cache
Parameters: cache – The cache to clear, one of (status, event, file, export, user)
-
cache_info()[source]¶ Retrieve cache info for the LRU caches used by this database
Returns: A dict of cache name (status, event, file, export, user) to cache info
-
camera_status_generator(sql, sql_args)[source]¶ Generator for
meteorpi_model.CameraStatusParameters: - sql – A SQL statement which must return rows with, in order: lens, sensor, instURL, instName, locationLatitude, locationLongitude, locationGPS, locationError, orientationAltitude, orientationAzimuth, orientationError, orientationRotation, widthOfField, validFrom, softwareVersion, internalID, statusID, cameraID
- sql_args – Any arguments required to populate the query provided in ‘sql’
Returns: A generator which produces
meteorpi_model.CameraStatusinstances from the supplied SQL, closing any opened cursors on completion
-
event_generator(sql, sql_args)[source]¶ Generator for Event
Parameters: - sql – A SQL statement which must return rows with, in order: camera ID, event ID, internal ID, event time, event semantic type, status ID
- sql_args – Any variables required to populate the query provided in ‘sql’
Returns: A generator which produces Event instances from the supplied SQL, closing any opened cursors on completion.
-
export_configuration_generator(sql, sql_args)[source]¶ Generator for
meteorpi_model.ExportConfigurationParameters: - sql – A SQL statement which must return rows with, in order: internalID, exportConfigID, exportType, searchString, targetURL, targetUser, targetPassword, exportName, description, active
- sql_args – Any variables required to populate the query provided in ‘sql’
Returns: A generator which produces
meteorpi_model.ExportConfigurationinstances from the supplied SQL, closing any opened cursors on completion.
-
file_generator(sql, sql_args)[source]¶ Generator for FileRecord
Parameters: - sql – A SQL statement which must return rows with, in order, internal ID, camera ID, mime type, semantic type, file time, file size, file ID, file name and file status ID.
- sql_args – Any variables required to populate the query provided in ‘sql’
Returns: A generator which produces FileRecord instances from the supplied SQL, closing any opened cursors on completion.
-
-
meteorpi_fdb.generators.first_from_generator(generator)[source]¶ Pull the first value from a generator and return it, closing the generator
Parameters: generator – A generator, this will be mapped onto a list and the first item extracted. Returns: None if there are no items, or the first item otherwise. Internal:
-
meteorpi_fdb.generators.first_non_null(values)[source]¶ Retrieve the first, non-null item in the specified list
Parameters: values – a list of values from which the first non-null is returned Returns: the first non-null item Raises: ValueError if there isn’t any such item in the list.
-
class
meteorpi_fdb.sql_builder.SQLBuilder(tables, where_clauses=None)[source]¶ Helper class to make it easier to build large, potentially complex, SQL clauses.
This class contains various methods to allow SQL queries to be built without having to manage enormous strings of SQL. It includes facilities to add metadata constraints, and to map from
meteorpi_model.NSStringanddatetime.datetimeto the forms we use within the firebird database (strings and big integers respectively). Also helps simplify the discovery and debugging of issues with generated queries as we can pull out the query strings directly from this object.-
__init__(tables, where_clauses=None)[source]¶ Construct a new, empty, SQLBuilder
Parameters: - where_clauses – Optionally specify an initial array of WHERE clauses, defaults to an empty sequence. Clauses specified here must not include the string ‘WHERE’, but should be e.g. [‘e.statusID = s.internalID’]
- tables – A SQL fragment defining the tables used by this SQLBuilder, i.e. ‘t_file f, t_cameraStatus s’
Variables: - where_clauses – A list of strings of SQL, which will be prefixed by ‘WHERE’ to construct a constraint. As with the init parameter these will not include the ‘WHERE’ itself.
- sql_args – A list of values which will be bound into an execution of the SQL query
Returns: An unpopulated SQLBuilder, including any initial where clauses.
-
add_metadata_query_properties(meta_constraints, meta_table_name)[source]¶ Construct WHERE clauses from a list of MetaConstraint objects, adding them to the query state.
Parameters: - meta_constraints – A list of MetaConstraint objects, each of which defines a condition over metadata which must be satisfied for results to be included in the overall query.
- meta_table_name – The name of the link table between the queried entity and metadata, i.e. t_eventMeta or t_fileMeta in the current code.
Raises: ValueError if an unknown meta constraint type is encountered.
-
add_set_membership(values, column_name)[source]¶ Append a set membership test, creating a query of the form ‘WHERE name IN (?,?...?)’.
Parameters: - values – A list of values, or a subclass of basestring. If this is non-None and non-empty this will add a set membership test to the state. If the supplied value is a basestring it will be wrapped in a single element list. Values are mapped by SQLBuilder._map_value before being added, so e.g. NSString instances will work here.
- column_name – The name of the column to use when checking the ‘IN’ condition.
-
add_sql(value, clause)[source]¶ Add a WHERE clause to the state. Handles NSString and datetime.datetime sensibly.
Parameters: - value – The unknown to bind into the state. Uses SQLBuilder._map_value() to map this into an appropriate database compatible type.
- clause – A SQL fragment defining the restriction on the unknown value
-
get_count_sql()[source]¶ Build a SELECT query which returns the count of items for an unlimited SELECT
Returns: A SQL SELECT query which returns the count of items for an unlimited query based on this SQLBuilder
-
get_select_sql(columns, order=None, limit=0, skip=0)[source]¶ Build a SELECT query based on the current state of the builder.
Parameters: - columns – SQL fragment describing which columns to select i.e. ‘e.cameraID, s.statusID’
- order – Optional ordering constraint, i.e. ‘e.eventTime DESC’
- limit – Optional, used to build the ‘FIRST n’ clause. If not specified no limit is imposed.
- skip – Optional, used to build the ‘SKIP n’ clause. If not specified results are returned from the first item available. Note that this parameter must be combined with ‘order’, otherwise there’s no ordering imposed on the results and subsequent queries may return overlapping data randomly. It’s unlikely that this will actually happen as almost all databases do in fact create an internal ordering, but there’s no guarantee of this (and some operations such as indexing will definitely break this property unless explicitly set).
Returns: A SQL SELECT query, which will make use of self.sql_args when executed. To run the query, use e.g.:
b = SQLBuilder() # Call add_sql etc methods on b here. sql = b.get_select_sql(columns='e.cameraID, e.eventID, e.internalID, e.eventTime', skip=search.skip, limit=search.limit, order='e.eventTime DESC') with closing(connection.cursor()) as cursor: cursor.execute(sql, b.sql_args) # do stuff with results
-
static
map_value(value)[source]¶ Perform type translation of values to be inserted into SQL queries based on their types.
Parameters: value – The value to map Returns: The mapped value. This will be the same as the input value other than two special cases: Firstly if the input value is an instance of model.NSString we map it to the stringified form ‘ns:value’. Secondly if the value is an instance of datetime.datetime we map it using model.utc_datetime_to_milliseconds, returning an integer.
-
-
meteorpi_fdb.sql_builder.search_events_sql_builder(search)[source]¶ Create and populate an instance of
meteorpi_fdb.SQLBuilderfor a givenmeteorpi_model.EventSearch. This can then be used to retrieve the results of the search, materialise them intometeorpi_model.Eventinstances etc.Parameters: search (EventSearch) – The search to realise Returns: A meteorpi_fdb.SQLBuilderconfigured from the supplied search
-
meteorpi_fdb.sql_builder.search_files_sql_builder(search)[source]¶ Create and populate an instance of
meteorpi_fdb.SQLBuilderfor a givenmeteorpi_model.FileRecordSearch. This can then be used to retrieve the results of the search, materialise them intometeorpi_model.FileRecordinstances etc.Parameters: search (FileRecordSearch) – The search to realise Returns: A meteorpi_fdb.SQLBuilderconfigured from the supplied search