1
0
Fork 0
mirror of https://github.com/archtechx/tenancy.git synced 2025-12-12 14:14:04 +00:00

Redis transactions

This commit is contained in:
Samuel Štancl 2019-09-19 19:54:06 +02:00
parent 27a93028b2
commit 032069af6d
4 changed files with 40 additions and 135 deletions

View file

@ -1,119 +0,0 @@
# Release Notes for 1.x
## [v1.8.0 (2019-08-17)](https://github.com/stancl/tenancy/compare/v1.7.0...v1.8.0)
### Added
- **Multi-tenant Jobs:** Jobs are now automatically multi-tenant. The [documentation page](https://stancl-tenancy.netlify.com/docs/jobs-queues/) covers the small tweaks you will have to make to your config to get multi-tenant jobs to work.
- **Telescope Integration**: You can read more about this on the [documentation page](https://stancl-tenancy.netlify.com/docs/telescope/).
- **Horizon Integration**: You can read more about this on the [documentation page](https://stancl-tenancy.netlify.com/docs/horizon/).
- **Tenant Redirect** and **Custom ID schemes**: You can now easily redirect to tenant domains. You can also use a custom tenant ID scheme if you don't like UUIDs. You can read about these features [here](https://stancl-tenancy.netlify.com/docs/misc-tips/).
### Fixed
- #112 *PostgreSQL Database creation error.*
### Code
- Strict types declaration is now used in every file.
## [v1.7.0 (2019-08-17)](https://github.com/stancl/tenancy/compare/v1.6.1...v1.7.0)
### Added:
- DB storage driver - you don't have to use Redis to store tenants anymore. Relational databases are now supported as well. [more info](https://stancl-tenancy.netlify.com/docs/storage-drivers/#database)
- `tenancy:install` will do everything except DB/Redis connection creation for you. It will make changes to Http/Kernel.php, create `routes/tenant.php`, publish config, and (optionally) publish the migration. [more info](https://stancl-tenancy.netlify.com/docs/installation/)
- `tenants:run` [more info](https://stancl-tenancy.netlify.com/docs/console-commands/#run)
- New documentation: https://stancl-tenancy.netlify.com
- Custom tenant DB names [more info](https://stancl-tenancy.netlify.com/docs/custom-database-names/)
- stancl/tenancy events [more info](https://stancl-tenancy.netlify.com/docs/event-system/)
### Fixed:
- #89 *Command "tenants:migrate" cannot be found when used in app code*
- #87 *Unable to migrate multiple tenants at once when using MySQL*
- #96 *Issue w/ redis->scan() in getAllTenants logic.*
## [v1.6.1 (2019-08-04)](https://github.com/stancl/tenancy/compare/v1.6.0...v1.6.1)
Multiple phpunit.xml configs are now generated to run the tests with different configurations, such as different Redis drivers.
### Fixed
- `tenancy()->all()` with predis [`0dc8c80`](https://github.com/stancl/tenancy/commit/0dc8c80a02efbee5676cc72e648e108037ca5268)
### Dropped
- Laravel 5.7 support [`65b3882`](https://github.com/stancl/tenancy/commit/65b38827d5a2fa183838a9dce9fb6a157fd7e859)
## [v1.6.0 (2019-07-30)](https://github.com/stancl/tenancy/compare/v1.5.1...v1.6.0)
### Added
- `GlobalCache` facade [#78](https://github.com/stancl/tenancy/pull/78)
## [v1.5.1 (2019-07-25)](https://github.com/stancl/tenancy/compare/v1.5.0...v1.5.1)
### Fixed
- Database is reconnected after migrating/rolling back/seeding is done [#71](https://github.com/stancl/tenancy/pull/71)
- Fixed tenant()->delete() (it used to delete the record from the `tenants` namespace but not the `domains` namespace) [#73](https://github.com/stancl/tenancy/pull/73)
## [v1.5.0 (2019-07-13)](https://github.com/stancl/tenancy/compare/v1.4.0...v1.5.0)
### Added
- PostgreSQL DB manager [#52](https://github.com/stancl/tenancy/pull/52)
- `tenancy()->end()` [#68](https://github.com/stancl/tenancy/pull/68)
### Fixed
- Return type docblock for `TenantManager::all()` [#63](https://github.com/stancl/tenancy/issue/63)
## [v1.4.0 (2019-07-03)](https://github.com/stancl/tenancy/compare/v1.3.1...v1.4.0)
### Added
- Predis support [#59](https://github.com/stancl/tenancy/pull/59)
## [v1.3.1 (2019-05-06)](https://github.com/stancl/tenancy/compare/v1.3.0...v1.3.1)
### Fixed
- Fix jobs [#38](https://github.com/stancl/tenancy/pull/38)
- Fix tests for 5.8 [#41](https://github.com/stancl/tenancy/issues/41)
## [v1.3.0 (2019-02-27)](https://github.com/stancl/tenancy/compare/v1.2.0...v1.3.0)
### Added
- Add 5.8 support [#33](https://github.com/stancl/tenancy/pull/33)
## [v1.2.0 (2019-02-15)](https://github.com/stancl/tenancy/compare/v1.1.3...v1.2.0)
### Added
- Add `Tenancy` facade [#29](https://github.com/stancl/tenancy/issues/29) [`987c54f`](https://github.com/stancl/tenancy/commit/987c54f04e6ff3bdef068d92da6a9ace847f6c37)
## [v1.1.3 (2019-02-13)](https://github.com/stancl/tenancy/compare/v1.1.2...v1.1.3)
### Fixed
- Fix CacheManager (it merged tags incorrectly), write tests for CacheManager [#31](https://github.com/stancl/tenancy/issues/31) [`a2d68b1`](https://github.com/stancl/tenancy/commit/a2d68b12611350f70befa3eb97fb56c99d006b54)
## [v1.1.2 (2019-02-13)](https://github.com/stancl/tenancy/compare/v1.1.1...v1.1.2)
### Fixed
- Fix small bug in CacheManager [`d4d4119`](https://github.com/stancl/tenancy/commit/d4d411975496272158d7823597427fad8966fff8)
## [v1.1.1 (2019-02-11)](https://github.com/stancl/tenancy/compare/v1.1.0...v1.1.1)
### Fixed
- Fix "Associative arrays are stored as objects" [#28](https://github.com/stancl/tenancy/issues/28)
## [v1.1.0 (2019-02-10)](https://github.com/stancl/tenancy/compare/v1.0.0...v1.1.0)
### Added
- Add array support to the storage [#27](https://github.com/stancl/tenancy/pull/27)

2
CHANGELOG-2.x.md Normal file
View file

@ -0,0 +1,2 @@
# Release Notes for 2.x

View file

@ -1,9 +1,9 @@
# [stancl/tenancy](https://tenancy.samuelstancl.me) # [stancl/tenancy](https://tenancy.samuelstancl.me)
[![Laravel 5.8](https://img.shields.io/badge/laravel-5.8-red.svg)](https://laravel.com) [![Laravel 6.x](https://img.shields.io/badge/laravel-6.x-red.svg)](https://laravel.com)
[![Latest Stable Version](https://poser.pugx.org/stancl/tenancy/version)](https://packagist.org/packages/stancl/tenancy) [![Latest Stable Version](https://poser.pugx.org/stancl/tenancy/version)](https://packagist.org/packages/stancl/tenancy)
[![Travis CI build](https://travis-ci.com/stancl/tenancy.svg?branch=1.x)](https://travis-ci.com/stancl/tenancy) [![Travis CI build](https://travis-ci.com/stancl/tenancy.svg?branch=2.x)](https://travis-ci.com/stancl/tenancy)
[![codecov](https://codecov.io/gh/stancl/tenancy/branch/1.x/graph/badge.svg)](https://codecov.io/gh/stancl/tenancy) [![codecov](https://codecov.io/gh/stancl/tenancy/branch/2.x/graph/badge.svg)](https://codecov.io/gh/stancl/tenancy)
### *A Laravel multi-database tenancy package that respects your code.* ### *A Laravel multi-database tenancy package that respects your code.*

View file

@ -7,14 +7,13 @@ namespace Stancl\Tenancy\StorageDrivers;
use Illuminate\Contracts\Redis\Factory as Redis; use Illuminate\Contracts\Redis\Factory as Redis;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Stancl\Tenancy\Contracts\StorageDriver; use Stancl\Tenancy\Contracts\StorageDriver;
use Stancl\Tenancy\Exceptions\DomainsOccupiedByOtherTenantException;
use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedException; use Stancl\Tenancy\Exceptions\TenantCouldNotBeIdentifiedException;
use Stancl\Tenancy\Exceptions\TenantWithThisIdAlreadyExistsException;
use Stancl\Tenancy\Tenant; use Stancl\Tenancy\Tenant;
// todo2 transactions instead of pipelines?
class RedisStorageDriver implements StorageDriver class RedisStorageDriver implements StorageDriver
{ {
// todo2 json encoding?
/** @var Application */ /** @var Application */
protected $app; protected $app;
@ -49,7 +48,17 @@ class RedisStorageDriver implements StorageDriver
public function ensureTenantCanBeCreated(Tenant $tenant): void public function ensureTenantCanBeCreated(Tenant $tenant): void
{ {
// todo2 // Tenant ID
if ($this->redis->exists("tenants:{$tenant->id}")) {
throw new TenantWithThisIdAlreadyExistsException($tenant->id);
}
// Domains
if ($this->redis->exists(...array_map(function ($domain) {
return "domains:$domain";
}, $tenant->domains))) {
throw new DomainsOccupiedByOtherTenantException;
}
} }
public function findByDomain(string $domain): Tenant public function findByDomain(string $domain): Tenant
@ -74,7 +83,7 @@ class RedisStorageDriver implements StorageDriver
public function createTenant(Tenant $tenant): void public function createTenant(Tenant $tenant): void
{ {
$this->redis->pipeline(function ($pipe) use ($tenant) { $this->redis->transaction(function ($pipe) use ($tenant) {
foreach ($tenant->domains as $domain) { foreach ($tenant->domains as $domain) {
$pipe->hmset("domains:$domain", ['tenant_id' => $tenant->id]); $pipe->hmset("domains:$domain", ['tenant_id' => $tenant->id]);
} }
@ -90,20 +99,34 @@ class RedisStorageDriver implements StorageDriver
public function updateTenant(Tenant $tenant): void public function updateTenant(Tenant $tenant): void
{ {
$this->redis->pipeline(function ($pipe) use ($tenant) { $data = [];
$pipe->hmset("tenants:{$tenant->id}", $tenant->data); // todo domains foreach ($tenant->data as $key => $value) {
$data[$key] = json_decode($value, true);
foreach ($tenant->domains as $domain) {
$pipe->hmset("domains:$domain", 'tenant_id', $tenant->id);
} }
// todo2 deleted domains $domains = $data['_tenancy_domains'];
unset($data['_tenancy_domains']);
$this->redis->transaction(function ($pipe) use ($data, $domains) {
$id = $data['id'];
$old_domains = json_decode($pipe->hget("tenants:$id", 'domains'), true);
$deleted_domains = array_diff($old_domains, $domains);
foreach ($deleted_domains as $deleted_domain) {
$pipe->del("domains:$deleted_domain");
}
$pipe->hmset("tenants:$id", array_merge($data, ['_tenancy_domains' => json_encode($domains)]));
foreach ($domains as $domain) {
$pipe->hmset("domains:$domain", 'tenant_id', $id);
}
}); });
} }
public function deleteTenant(Tenant $tenant): void public function deleteTenant(Tenant $tenant): void
{ {
$this->redis->pipeline(function ($pipe) use ($tenant) { $this->redis->transaction(function ($pipe) use ($tenant) {
foreach ($tenant->domains as $domain) { foreach ($tenant->domains as $domain) {
$pipe->del("domains:$domain"); $pipe->del("domains:$domain");
} }
@ -120,7 +143,6 @@ class RedisStorageDriver implements StorageDriver
*/ */
public function all(array $ids = []): array public function all(array $ids = []): array
{ {
// todo2 $this->redis->pipeline()
$hashes = array_map(function ($hash) { $hashes = array_map(function ($hash) {
return "tenants:{$hash}"; return "tenants:{$hash}";
}, $ids); }, $ids);