* Add service manager infrastructure
The changes are (This will be a bit long):
- A ServiceManager class that spawns a background thread and deals with
service lifecycle management. The idea is that service lifecycle code
will run in async functions, so a single thread is enough to manage
any (reasonable) amount of services.
- A Service class, that offers start(), stop() and restart() methods
that simply notify the service manager to... well. Start, stop or
restart a service.
(!) Warning: Note that this differs from mp.Process.start/stop in that
the service commands are sent asynchronously and will complete
"eventually". This is good because it means that business logic is
fast when booting up and shutting down, but we need to make sure
that code does not rely on start() and stop() being instant
(Mainly pid assignments).
Subclasses of the Service class should use the on_start and on_stop
methods to monitor for service events. These will be run by the
service manager thread, so we need to be careful not to block
execution here. Standard async stuff.
(!) Note on service names: Service names should be unique within a
ServiceManager. Make sure that you pass the name you want to
super().__init__(name="...") if you plan to spawn multiple instances
of a service.
- A ServiceProcess class: A Service that wraps a multiprocessing.Process
into a Service. It offers a run() method subclasses can override and
can support in-place restarting using the service manager.
And finally, I lied a bit about this whole thing using a single thread.
I can't find any way to run python multiprocessing in async, so there is
a MultiprocessingWaiter thread that waits for multiprocessing events and
notifies any pending futures. This was uhhh... fun? No, not really.
But it works. Using this part of the code just involves calling the
provided wait method. See the implementation of ServiceProcess for more
details.
Mirror util.Process hooks onto service process
Remove Service.__name attribute
Do not serialize process object on ServiceProcess start.
asd
* Update frigate dictionary
* Convert AudioProcessor to service process
* swap sqlite_vec for chroma in requirements
* load sqlite_vec in embeddings manager
* remove chroma and revamp Embeddings class for sqlite_vec
* manual minilm onnx inference
* remove chroma in clip model
* migrate api from chroma to sqlite_vec
* migrate event cleanup from chroma to sqlite_vec
* migrate embedding maintainer from chroma to sqlite_vec
* genai description for sqlite_vec
* load sqlite_vec in main thread db
* extend the SqliteQueueDatabase class and use peewee db.execute_sql
* search with Event type for similarity
* fix similarity search
* install and add comment about transformers
* fix normalization
* add id filter
* clean up
* clean up
* fully remove chroma and add transformers env var
* readd uvicorn for fastapi
* readd tokenizer parallelism env var
* remove chroma from docs
* remove chroma from UI
* try removing custom pysqlite3 build
* hard code limit
* optimize queries
* revert explore query
* fix query
* keep building pysqlite3
* single pass fetch and process
* remove unnecessary re-embed
* update deps
* move SqliteVecQueueDatabase to db directory
* make search thumbnail take up full size of results box
* improve typing
* improve model downloading and add status screen
* daemon downloading thread
* catch case when semantic search is disabled
* fix typing
* build sqlite_vec from source
* resolve conflict
* file permissions
* try build deps
* remove sources
* sources
* fix thread start
* include git in build
* reorder embeddings after detectors are started
* build with sqlite amalgamation
* non-platform specific
* use wget instead of curl
* remove unzip -d
* remove sqlite_vec from requirements and load the compiled version
* fix build
* avoid race in db connection
* add scale_factor and bias to description zscore normalization
* Added stop_event to util.Process
util.Process will take care of receiving signals when the stop_event is
accessed in the subclass. If it never is, SystemExit is raised instead.
This has the effect of still behaving like multiprocessing.Process when
stop_event is not accessed, while still allowing subclasses to not deal
with the hassle of setting it up.
* Give each util.Process their own logger
This will help to reduce boilerplate in subclasses.
* Give explicit types to util.Process.__init__
This gives better type hinting in the editor.
* Use util.Process facilities in AudioProcessor
Boilerplate begone!
* Removed pointless check in util.Process
The log_listener.queue should never be None, unless something has gone
extremely wrong in the log setup code. If we're that far gone, crashing
is better.
* Make sure faulthandler is enabled in all processes
This has no effect currently since we're using the fork start_method.
However, when we inevidably switch to forkserver (either by choice, or
by upgrading to python 3.14+) not having this makes for some really fun
failure modes :D
* Allow embedding of snapshot for description via config option
* docs
* frontend button
* Backend
* crop snapshot to region
* only show dropdown when event has snapshot
* fix cursor on dropdown
* crop on initial generation as well
* use enum for type
* fix type
* Subclass Process for audio_process
* Introduce custom mp.Process subclass
In preparation to switch the multiprocessing startup method away from
"fork", we cannot rely on os.fork cloning the log state at fork time.
Instead, we have to set up logging before we run the business logic of
each process.
* Make camera_metrics into a class
* Make ptz_metrics into a class
* Fixed PtzMotionEstimator.ptz_metrics type annotation
* Removed pointless variables
* Do not start audio processor when no audio cameras are configured
* Moved FrigateApp.init_config() into FrigateConfig.load()
* Move frigate config loading into main
* Store PlusApi in FrigateConfig
* Register SIGTERM handler in main
* Ensure logging is setup during config parsing
* Removed pointless try
* Moved config initialization out of FrigateApp
* Made FrigateApp.shm_frame_count into a function
* Removed log calls from signal handlers
python's logging calls are not re-entrant, which caused at least one of
these to deadlock randomly.
* Reopen stdout/err on process fork
This helps avoid deadlocks (https://github.com/python/cpython/issues/91776).
* Make mypy happy
* Whoops. I might have forgotten to save.
Truly an amateur mistake.
* Always call FrigateApp.stop()
* Install multiple ffmpeg versions and add config to make it configurable
* Update docs
* Run ffprobe too
* Cleanup
* Apply config to go2rtc as well
* Fix ffmpeg bin
* Docs
* Restore path
* Cleanup env var
* Fix ffmpeg path for encoding
* Fix export
* Formatting
* Refactor recordings config to be based off of review items
* Update object processing logic for when an event is created
* Migrate to deciding recording retention based on review items
* Refactor recording expiration to be based off of review items
* Remove remainder of recording events access
* Handle migration automatically
* Update version and cleanup
* Update docs
* Clarify docs
* Cleanup
* Target camera config
* Safely access all fields
* Initial re-implementation of semantic search
* put docker-compose back and make reindex match docs
* remove debug code and fix import
* fix docs
* manually build pysqlite3 as binaries are only available for x86-64
* update comment in build_pysqlite3.sh
* only embed objects
* better error handling when genai fails
* ask ollama to pull requested model at startup
* update ollama docs
* address some PR review comments
* fix lint
* use IPC to write description, update docs for reindex
* remove gemini-pro-vision from docs as it will be unavailable soon
* fix OpenAI doc available models
* fix api error in gemini and metadata for embeddings
* intentionally handle queues during shutdown and carefully manage shutdown order
* more carefully manage shutdown to avoid threadlocks
* use debug for signal logging
* ensure disabled cameras dont break shutdown
* typo
* Restrict nginx to 4 processes if more are available
* Fix bash
* Different sed structure
* Limit ffmpeg thread counts for secondary ffmpeg processes
* Add up / down keyboard shortcut
* Fix external events saving
* Only show relevant labels
* Set on recordings view too
* Fix video control width on motion page
* use overlay so player state is maintained between camera switches
* use overlay so player state is maintained between camera switches
* mobile only
* Formatting
* Use higher amount
* Only wrap when needed
* Add verification for required zone names
* Make global object masks use relative coordinates as well
* Ensure event image cleanup doesn't fail
* Return passed value
* Update review maintainer to save events when ongoing
* Handle previews for in progress review items
* Reset DB items in app
* Handle in progress review items
* Scroll back down to selected event item
* Handle undefined end time
* Formatting
* remove unused
* Make export handles have full resolution
* reduce preview thumbnail props
* fix missing return
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
---------
Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
* Only update frame time if it is older
* Support manual detections as review items
* Don't handle api detections in recordings
* Store recordings for manual events
* Add config pub / sub pattern
* remove recording from feature metrics
* remove audio and feature metrics
* Check for updates from all cameras
* remove birdseye from camera metrics
* remove motion and detection camera metrics
* Ensure that all processes are stopped
* Stop communicators
* Detections
* Cleanup video output queue
* Use select for time sensitive polls
* Use ipc instead of tcp
* Use zmq for inter process communication
* Use localhost for reply and request
* Use pyobj instead of json and Need to use separate requestors for each audio listener
* Cleanup port defining
* Add filter popover
* Add api filter hook and use UI with filtering
* Get history filtering working for cameras and labels
* Allow filtering on detail level
* Save timeline entries for api events
* reset
* fix width
* Add support for review grid
* Cleanup reloading on focus
* Adjust timeline api to include metadata and before
* Be more efficient about getting info
* Adjust to new data format
* Cleanup types
* Cleanup text
* Transition to history
* Cleanup
* remove old web implementations
* Cleanup
* Add attribute item to timeline
* Add face icon
* Add support for other icons
* Cleanup
* Ensure attributes are only updated once
* don't show _ in attributes
* Reduce database queries to necessary labels
* Set columns for other queries
* skip creating model instances
---------
Co-authored-by: Blake Blackshear <blakeb@blakeshome.com>