Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Gps Messenger Bundle Laravel Package

genesis-global/gps-messenger-bundle

genesis-global/gps-messenger-bundle integrates GPS messenger capabilities into PHP/Laravel applications, providing configurable messaging services for sending, receiving, and handling location-aware messages with simple framework wiring.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and register. This is a Symfony bundle, not a Laravel package — the only Laravel-relevant path is composer require genesis-global/gps-messenger-bundle into a project that already pulls Symfony components, and then registering the bundle manually (no Flex recipe ships with a 0-star fork, so add it to config/bundles.php / app/AppKernel.php yourself). Confirm the fork actually relaxed the PHP constraint by reading its composer.json before you commit.

2. Provision GCP first. The transport is a thin wrapper around google/cloud-pubsub; it does not manage infrastructure for you. Create the topic and subscription (gcloud pubsub topics create, gcloud pubsub subscriptions create) and grant the runtime service account roles/pubsub.publisher (producer side) and roles/pubsub.subscriber (consumer side). Credentials come from GOOGLE_APPLICATION_CREDENTIALS or the transport's client-config option.

3. Configure the transport. The DSN scheme is gps://; project/topic/subscription are passed as options (verify exact key names in DependencyInjection/Configuration.php, they differ slightly between upstream revisions):

# config/packages/messenger.yaml
framework:
    messenger:
        transports:
            gps:
                dsn: 'gps://'
                options:
                    project_id: '%env(GPS_PROJECT_ID)%'
                    topic_name: 'orders'
                    subscription_name: 'orders-worker'
                    # batch_size: 100          # 1.3+: publish in batches
                    # client_config: '%kernel.project_dir%/config/gcp-service-account.json'
        routing:
            'App\Message\OrderPlaced': gps

4. First use case. Dispatch a plain message object onto the bus, then run the consumer in a worker:

$bus->dispatch(new OrderPlaced($orderId));
// $ bin/console messenger:consume gps -vv

Where to look first, in this order: GpsTransportFactory (what DSN/options are actually accepted — including batch_size as of 1.3), GpsSender (now the batching logic lives here: buffer, flush trigger, publishBatch call), GpsReceiver (the pull loop, ack/nack semantics, ack-deadline default), then DependencyInjection/Configuration.php. Those four files are the entire surface area of the package; everything else is Symfony Messenger.

Reality check before you build on it: this is still a fork whose only stated purpose was PHP 7.3 support, zero dependents, one original release in 2021. 1.3 is the first substantive release since — it adds batch_size and caches the topic-existence check per process. That's a genuine improvement, not a bugfix train, so the maintenance-risk caveat still stands: if your project is on PHP 7.4+ or Symfony 5.3+, compare against upstream petitpress/gps-messenger-bundle (check whether these two features landed there too) and treat this fork as a temporary pin.

Implementation Patterns

Treat the transport as a MessageBroker, not an event bus. One transport = one topic + one subscription. Model your domain as a handful of topics (e.g. orders, notifications) and route message classes explicitly rather than dumping everything on a single gps transport — Pub/Sub has no routing or filtering at the transport layer, so the split is purely a deployment/consumer-scaling decision.

Turn on batch_size for producer-heavy workloads, and understand what you're buying. 1.3 batches publishes into a single publishBatch call, which cuts per-message HTTP/API overhead and is the single biggest throughput win available without touching GCP quotas. The trade-off is latency and failure granularity: a message handed to the bus may sit in the buffer until the batch fills (or the transport flushes), and a partial batch failure surfaces as one send result, so your dispatch-side error handling has to be coarse. Keep batch_size unset (or 1) for low-volume, latency-sensitive topics like transactional notifications; raise it (50–100) for high-fan-out event topics.

Flush discipline matters in workers and short-lived processes. If you enable batching inside a messenger:consume process, remember that the sender holds a buffer across messages — make sure your process actually drains before exit (--time-limit shutdown, container SIGTERM) or you drop the tail of the buffer. In a web request that dispatches a handful of messages then returns, a large batch_size means nothing gets published until the request ends; size it to your realistic per-request volume.

Use JSON serialization, not PHP serialization, if anything outside PHP touches the topic. Symfony's default messenger.transport.native_php_serializer produces payloads no other language can read. Switch the Messenger serializer to the Symfony Serializer with a JSON encoder, and accept that the type header travels in the Pub/Sub message attributes — a Go/Node consumer must read that attribute or decode the wrapper to know the class. Validate the byte-for-byte layout with a real gcloud pubsub subscriptions pull before designing around it. Note this interacts with batching: verify the per-message attributes are preserved per-message in a batch, not collapsed onto the first one.

Consumers are long-running workers, so treat deployment like a queue daemon. Run messenger:consume gps --time-limit=3600 --memory-limit=128M under supervisor/systemd, not cron. Pub/Sub delivers each message to exactly one subscriber on a subscription, so horizontal scaling is just "run more of these containers with the same subscription name" — no sharding config needed. Use distinct subscription names per environment and per logical consumer group; two services sharing one subscription will steal each other's messages.

Handle redelivery, because Pub/Sub is at-least-once. A thrown exception in the handler means nack, and the message comes back. Wire up Messenger's retry strategy with exponential backoff and a failure_transport, and make handlers idempotent keyed on your own business identifier (order ID, event ID) rather than relying on exactly-once delivery. This is the single most common production surprise with this bundle — and 1.3's batching makes it slightly worse on the producer side, since a batch that half-succeeds may be retried whole. Make publish-side idempotency (or duplicate-tolerant consumers) non-optional once batching is on.

Keep the handler fast relative to the ack deadline. Pub/Sub's default ack deadline is 10 seconds (configurable to 600 max). A handler that takes 45 seconds will get its message redelivered and processed twice. Split slow work into a second dispatch to another transport, or raise the subscription's ack deadline in GCP infrastructure-as-code.

Test by swapping the DSN, not by mocking the transport. In the test environment override framework.messenger.transports.gps.dsn with in-memory:// or sync:// so the same routing config exercises handlers directly. If you need to assert on the wire format — important now that batching changes the publish shape — use the Pub/Sub emulator (PUBSUB_EMULATOR_HOST=localhost:8085) — but first confirm the fork's client construction respects that env var rather than always building an authenticated client.

Bridging from Laravel. If this lives inside a Laravel app, publish via Laravel's job dispatch or a small service that wraps MessageBusInterface, and run the consumer as a second process (php artisan command that calls messenger:consume via the Symfony console kernel, or a standalone Symfony worker container). Don't try to make Laravel's queue worker drive this transport; the two have incompatible retry/ack models.

Cross-language producers. Anything else publishing to the topic must replicate the envelope Symfony's serializer expects. Practically: publish JSON whose shape matches what your handler's message class deserializes from, and set the type attribute correctly. Keep a shared schema (or at least a contract test) so a Node producer and a PHP consumer don't drift.

Gotchas and Tips

  • The fork is still the biggest risk, not the code. Zero stars, one release in 2021, and now a 1.3 that bundles two features — one of which (per-process topic caching) changes lifecycle semantics. Read the 1.3 diff before adopting: batch_size defaults and the exact caching scope are worth knowing precisely. Pin the exact version in composer.lock, and if you're on PHP 8, this remains a dead end; go upstream or talk to whoever owns the fork.
  • 1.3's topic-existence caching means topic creation must happen before the process starts. The transport now checks the topic exists once per process instead of per publish — great for long-running worker latency and API quota, but it means a worker started before the topic existed (or before a topic rename) will not self-heal. Provision the topic, then start/restart publishers. If you're doing blue/green topic cutovers, plan for a restart, not a hot swap.
  • batch_size changes the meaning of "dispatched". With batching on, dispatch() returning successfully no longer means the message is in Pub/Sub — it means it's buffered. Don't build read-after-write flows on top of a batched transport, and don't assume a caught exception means nothing was published (partial batches). For transactional outbox patterns, flush explicitly or keep that transport unbuffered.
  • Missing project_id fails late and cryptically. Misconfiguration surfaces as a Google client exception at dispatch/consume time, not at container compile time. Add a smoke test that boots the container and asserts the transport service exists — with 1.3's caching, a misconfigured topic surfaces at the first publish of the process, which is even later than before.
  • Topic must exist before first publish. The transport sends; it doesn't create. A NotFound on your first dispatch is infrastructure, not your message class. Prefer Terraform/gcloud provisioning over hoping for auto-creation (and check GpsReceiver's behavior — some revisions create the subscription lazily, some don't).
  • Credential resolution is the usual local-dev blocker. Either set GOOGLE_APPLICATION_CREDENTIALS or pass an explicit client config path. Watch file permissions inside containers and avoid committing the JSON.
  • Blocking pull loop + Messenger flags. --sleep, and some rate-limiting options, behave differently than with AMQP/Redis because the receiver blocks on pull(). Tune batching/max-messages in the transport options if throughput is a concern; use --time-limit plus supervisor restart to bound memory growth.
  • Service state leakage between messages. Enable framework.messenger.reset_on_message: true so Doctrine connections and other services are reset, and remember Doctrine connections die over long worker lifetimes regardless.
  • Message size and ordering. Pub/Sub caps messages at 10 MB and the bundle exposes no ordering-key plumbing — if you need per-entity ordering, key it yourself and route to a single consumer, or this is the wrong tool. Batching does not give you ordering; a batch is not a sequence guarantee.
  • Debugging workflow. messenger:consume gps -vvv for handler-level detail, gcloud pubsub subscriptions pull orders-worker --auto-ack --limit=5 to inspect raw payloads and attributes, and GCP's Pub/Sub metrics for oldest_unacked_message_age (a rising value means your workers are down or wedged). With batching on, also watch publish latency and batch-failure counts — a stuck buffer looks identical to "nothing is being dispatched."
  • Extension points. Decorate GpsReceiver to add logging/metrics around ack/nack, replace the transport-factory service to inject a custom PubSubClient (useful for publish batching tuning or emulator support), and override the serializer on the transport if you need a custom envelope format. If 1.3's batching doesn't fit your flush semantics, subclassing GpsSender is now the natural seam.
  • Failure recovery. Configure failure_transport and a messenger:failed:show/retry runbook; without it, poison messages cycle until Pub/Sub's own redelivery gives up and they land in whatever dead-letter policy you (hopefully) configured at the subscription level.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator