PHPackages                             nawasara/sync - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. nawasara/sync

ActiveLibrary[Queues &amp; Workers](/categories/queues)

nawasara/sync
=============

Foundation for the DB-cache + queue pattern shared across Nawasara service packages (WHM, Cloudflare, Keycloak, etc.) — sync job tracker, repository contract, snapshot trait, and audit UI.

v0.1.1(1mo ago)0447MITPHPPHP ^8.1

Since May 7Pushed 1mo agoCompare

[ Source](https://github.com/nawasara/sync)[ Packagist](https://packagist.org/packages/nawasara/sync)[ RSS](/packages/nawasara-sync/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (4)Versions (3)Used By (7)

Nawasara Sync
=============

[](#nawasara-sync)

The foundation package for the **DB-cache + queue pattern** used across every Nawasara service integration. Provides the sync-job tracker, repository contract, snapshot trait, audit log UI, and a system-health dashboard.

The pattern
-----------

[](#the-pattern)

External services (Cloudflare, WHM, Keycloak, etc.) are slow, rate-limited, and unreliable. Hitting them on every page render is wrong. Instead, every Nawasara service package follows this shape:

```
External API  ◄─────  Mutation Job (queue)  ◄─────  User action
     │
     ▼  scheduled / on-demand sync
DB snapshot  ─────►  Repository  ─────►  Livewire page (paginated, fast)

```

- **Reads** come from a local snapshot table (paginated, indexed, fast)
- **Writes** dispatch queued mutation jobs that update the external API and the local snapshot atomically with content-hash conflict detection
- **Audit log** at `/admin/sync/jobs` records every dispatched job (action, target, user, payload with sensitive fields masked, status, duration, error)

What this package ships
-----------------------

[](#what-this-package-ships)

- **`SyncJob` model** — the audit row for every queued action across every package
- **`AbstractSyncJob`** — base for queued mutation/sync jobs. Auto-creates the tracker row in the constructor, marks it running/success/failed/conflict in `handle()`, and masks sensitive payload keys (password, secret, token, key) before persisting
- **`SyncedRepository`** contract — `list / find / all / create / update / delete / syncNow / lastSyncedAt`. Every service package implements this consistently
- **`HasSyncStatus` trait** — adds `sync_status`, `sync_error`, `last_synced_at`, and `content_hash` columns plus convenience scopes (`pendingSync`, `failed`, `synced`) and helpers (`markPending`, `markSynced`, `markFailed`)
- **`TracksLastSync` trait** — repository helper that resolves the last successful sync time from `nawasara_sync_jobs` instead of from per-record `last_synced_at` (which only updates when content changes)
- **``** — pill component that visualises a row's sync state in tables
- **System Health** at `/admin/sync/health` — totals, per-service breakdown with success rate, recent failures, and a window switcher
- **Sync Jobs** at `/admin/sync/jobs` — searchable, filterable audit log with retry and detail modal

Installation
------------

[](#installation)

```
composer require nawasara/sync
php artisan migrate
php artisan db:seed --class="Nawasara\Sync\Database\Seeders\PermissionSeeder" --force
```

Auto-discovered.

Implementing a service package
------------------------------

[](#implementing-a-service-package)

```
use Nawasara\Sync\Concerns\HasSyncStatus;
use Nawasara\Sync\Concerns\TracksLastSync;
use Nawasara\Sync\Contracts\SyncedRepository;
use Nawasara\Sync\Jobs\AbstractSyncJob;

// 1. Snapshot model
class WhmEmailAccount extends Model
{
    use HasSyncStatus;

    public function computeContentHash(): string
    {
        return hash('sha256', json_encode([
            'email' => $this->email,
            'quota_mb' => $this->quota_mb,
            // … fields you want to detect drift on
        ]));
    }
}

// 2. Repository
class WhmEmailAccountRepository implements SyncedRepository
{
    use TracksLastSync;

    public function list(array $filters = [], int $perPage = 25) { /* ... */ }
    public function create(array $data): ?SyncJob { /* dispatch CreateWhmEmailJob */ }
    public function update($id, array $data): ?SyncJob { /* dispatch ChangeWhmEmail*Job */ }
    public function delete($id): ?SyncJob { /* dispatch DeleteWhmEmailJob */ }
    public function syncNow(): ?SyncJob { /* dispatch SyncWhmEmailsJob */ }

    public function lastSyncedAt(): ?Carbon
    {
        return $this->lastSuccessfulSyncAt('whm', 'sync_emails');
    }
}

// 3. Job
class ChangeWhmEmailQuotaJob extends AbstractSyncJob
{
    protected function service(): string { return 'whm'; }
    protected function action(): string { return 'quota_email'; }
    protected function targetType(): ?string { return 'WhmEmailAccount'; }
    protected function targetId(): ?string { return $this->payload['email']; }

    protected function execute(): array
    {
        // call external API…
        // update snapshot row…
        return ['quota_mb' => $newQuota];
    }
}
```

Permissions
-----------

[](#permissions)

PermissionDescription`sync.job.view`View sync jobs audit log`sync.job.manage`Retry or delete sync job rowsAuthor
------

[](#author)

**Pringgo J. Saputro** &lt;&gt;

License
-------

[](#license)

MIT

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance94

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity33

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

2

Last Release

30d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/16914951?v=4)[Pringgo J. Saputro](/maintainers/pringgojs)[@pringgojs](https://github.com/pringgojs)

![](https://www.gravatar.com/avatar/edcf770bde3babcc9fa554e305e361b8614c1e505470e75842de75ea3e502548?d=identicon)[nawasara](/maintainers/nawasara)

---

Top Contributors

[![pringgojs](https://avatars.githubusercontent.com/u/16914951?v=4)](https://github.com/pringgojs "pringgojs (17 commits)")

---

Tags

laravelqueuerepository patternsyncaudit-logdb-cacheNawasara

### Embed Badge

![Health badge](/badges/nawasara-sync/health.svg)

```
[![Health](https://phpackages.com/badges/nawasara-sync/health.svg)](https://phpackages.com/packages/nawasara-sync)
```

###  Alternatives

[venturedrake/laravel-crm

A free open source CRM built as a package for laravel projects

39910.0k](/packages/venturedrake-laravel-crm)[nasirkhan/laravel-starter

A CMS like modular Laravel starter project.

1.4k2.7k](/packages/nasirkhan-laravel-starter)[tallstackui/tallstackui

TallStackUI is a powerful suite of Blade components that elevate your workflow of Livewire applications.

719160.4k12](/packages/tallstackui-tallstackui)[yajra/laravel-datatables-export

Laravel DataTables Queued Export Plugin.

352.1M4](/packages/yajra-laravel-datatables-export)[harris21/laravel-fuse

Circuit breaker for Laravel queue jobs. Protect your workers from cascading failures.

24740.3k](/packages/harris21-laravel-fuse)[tomshaw/electricgrid

A feature-rich Livewire package designed for projects that require dynamic, interactive data tables.

119.2k](/packages/tomshaw-electricgrid)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
