GithubHelp home page GithubHelp logo

spiritix / lada-cache Goto Github PK

View Code? Open in Web Editor NEW
532.0 532.0 68.0 352 KB

A Redis based, fully automated and scalable database cache layer for Laravel

License: MIT License

PHP 99.67% Dockerfile 0.33%
cache caching database eloquent laravel laravel-5-package php redis

lada-cache's People

Contributors

dependabot[bot] avatar diegotibi avatar ethaizone avatar fridzema avatar genesiscz avatar knightar avatar laravel-shift avatar mehrdad-dadkhah avatar mga-kontainer avatar miraries avatar odiaseo avatar qodeboy avatar savornicesei avatar spiritix avatar swanty avatar tof06 avatar xwiz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lada-cache's Issues

Refactor reflectors

The reflector concept should be removed and replaced with a single reflector based on Query\Builder.
After having this implemented it won't be required anymore to extend the Lada Cache model.

lada-cache:flush generates Redis-Cluster error - cannot use "KEYS"

Laravel: v5.6.16

Trying to run lada-cache:flush before a new migration (and also trying to run the db:seed command)
generates a redis error:

panel.vm $ php artisan lada-cache:flush

   Predis\NotSupportedException  : Cannot use 'KEYS' with redis-cluster.

This is my database.php config:

'redis' => [

        'client' => 'predis',

        'options' => [
            'cluster' => 'redis',
        ],

        'clusters' => [
            'default' => [
                'host' => env('REDIS_HOST', 'localhost'),
                'password' => env('REDIS_PASSWORD', null),
                'port' => env('REDIS_PORT', 6379),
                'database' => 0,
            ],
        ],

    ],

Eloquent paginate is ignored and pages display the same results

Sorry for opening all these issues haha, but it seems to be a bug.

$domains = Domain::orderBy('updated_at', 'desc')
                         ->paginate(10);

Got any solution for this? I checked the issues but couldn't find pagination problems.

Results (table has 30 unique domain names):
screen shot 2018-04-19 at 4 36 04 pm
screen shot 2018-04-19 at 4 36 14 pm
screen shot 2018-04-19 at 4 36 22 pm

screen shot 2018-04-19 at 4 38 50 pm

Improve the reflector tests

They are quite basic at the moment. We should not mock these very basic QueryBuilders and Models but instead have testing stubs and use them like real world examples.

Cache not clearing

Hey,

Great package, thanks for releasing and maintaining this.

I currently have a problem that I just noticed, it was fine until a few hours ago.

The cache on my website doesn't get cleared when new "items" get added to the database. It doesn't happen with every model, just with a particular one.

It's quite odd to describe and it works just fine on my local env.

Here's a URL in case you want to see it: https://insegreto.com/it/fresh

In that page you'll find a list of posts. New posts are not visible until I manually clear the cache but you can see new comments right away.

I know the info is not much, but maybe you have already an idea of what's happening? Or maybe you can recommend a way to debug this?

--- EDIT
More info. I'm using Envoyer to manage my deployments and after re-deploying (same code) everything is working as expected. I would expect though to have the same issue again in a few hours. Will keep posted.

--- EDIT #2
So.. after 6 hours, here we go again. Same issue. This time, re-deploying didn't fix the issue. I had to run php artisan lada-cache:flush.

updateExistingPivot method doesn't invalidate data

Just wondering if there is a way to bypass the cache. For example, while doing a cron job and wanting direct query result, not a cached version. Or, do I simply need to flush the cache before doing the cron job?

Thanks

Reflector doesn't get table for N-N relations

Hey there,

first of all, very great package! but i've got a problem having a user and group model
where group has users() and user has groups() many-to-many relation.
for some reason if i update the relation from user model everything is fine. but if i update from group model the old relations stay cached and won't show.

any idea on why that is?
i'm pretty new to laravel and couldn't fine the hook u use to detect and flush cache on using attach() or detach() where are those located?

[EDIT] this is what i do for the update:

                $group->display_name = Input::get('display_name');
                $group->description = Input::get('description');
                $group->save();

                // remove all existing users and set only checked
                if (\Auth::User()->can('group-assign-user')) {
                    $group->users()->detach();
                    $new_users = (Array)Input::get('users');
                    foreach ($new_users as $user) {
                        $group->users()->attach($user);
                    }
                }

Issue using withCount on belongsToMany

When trying to use withCount() on a belongsToMany relationship, it fails with this message:

Argument 1 passed to Spiritix\LadaCache\QueryHandler::setBuilder() must be an instance of Spiritix\LadaCache\Database\QueryBuilder, instance of Illuminate\Database\Query\Builder given, called in /home/vagrant/project/vendor/spiritix/lada-cache/src/Spiritix/LadaCache/Database/QueryBuilder.php on line 84

If I removed lada-cache trait, it returns the expected count. I'm using this on hasMany relationships too. lada-cache seems to work fine with those.
Any ideas on how to fix this?

Memory exhausted using Scout

Hello

Running the command php artisan scout:import App\Model it results in a fatal error thrown by lada cache:

Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes) in /home/runcloud/webapps/laravel-vivicity/vendor/spiritix/lada-cache/src/Spiritix/LadaCache/Encoder.php on line 43

Unable to select which REDIS configuration is used

Note that since Laravel 5.7

php artisan cache:clear will not clear the default REDIS connection that lada-cache is configured to use (and doesn't appear to have any way to change)

This means that currently lada-cache is using the 'database' configuration of REDIS in Laravel (called 'default') (for things like sessions) and not the 'cache' configuration (called 'cache') .

The only work around I can see at the moment, is to change the redis cache configuration in Laravel (/app/config/cache.php) to have it's connection set to the 'default' and not 'cache'.

This of course undoes the reason it was changed in the first place, doing php artisan cache:clear will also delete anything placed in the REDIS 'database' configuration (i.e. sessions and the like)

Laravel 6 support

Is there any ETA for Laravel 6 support? And will there be Lumen support also?

Any plans on making it work with Lumen

I have built a read-only API that does heavy database querying and would like to use this project. I tried to install and it failed at vendor:publish with the following error.

I'm asking this with the an anticipation that it requires less work to support Lumen. If not, that's fine, let me know. Thanks!

php artisan vendor:publish
PHP Fatal error:  Call to undefined method Laravel\Lumen\Application::share() in /Users/bhargav/Projects/myfyba/api/vendor/spiritix/lada-cache/src/Spiritix/LadaCache/LadaCacheServiceProvider.php on line 138

Fatal error: Call to undefined method Laravel\Lumen\Application::share() in /Users/bhargav/Projects/myfyba/api/vendor/spiritix/lada-cache/src/Spiritix/LadaCache/LadaCacheServiceProvider.php on line 138

                                                               
  [Symfony\Component\Debug\Exception\FatalErrorException]      
  Call to undefined method Laravel\Lumen\Application::share() 

Maybe add a How It Works section to README.md

This project looks great, but I had some technical questions about how lada-cache actually works.

  1. Does it make an MD5 of the query via toSql() or another object and check if that exists?
  2. How would I inspect the keys created by lada-cache in Redis CLI?
  3. How long are the TTLs for query results cached?
  4. If a new field data is written to the db, how does the query cached become invalidated?
  5. How are cached query results serialized into Redis?
  6. Can it be used with PHPRedis (not Predis)?

Without looking at the actual source code it is difficult to understand what is actually happening, which, I believe, is an important factor to decide if this library is right for me.

Question: Nested queries with dynamic whereHas & where

Hey,

thanks a lot for making this awesome package.

I'm playing around with it and it seems to do everything I need, but wanted to ask if will reliably cache nested queries like the following (If I add primary keys named ID to all pivot tables):

Would this create different cached versions for the below query based on the dynamic variables, or would the dynamic parts invalidate the cache every time a visitor hits my site from another country, OS, device type etc.

return $this->domain->load([
                    'advertisers' => function ($q) {
                        $q->with([
                            $this->adsRelationship => function ($q) {
                                $q->whereHas('countries', function ($q) {
                                    $q->whereIn('key', [session('country_code'), 'XX']);
                                })
                                  ->whereHas('operatingSystems', function ($q) {
                                      $q->whereIn('key', [session('os'), 'all']);
                                  })
                                  ->whereHas('deviceTypes', function ($q) {
                                      $q->whereIn('key', [session('device_type'), 'all']);
                                  })
                                  ->whereHas('browsers', function ($q) {
                                      $q->whereIn('key', [session('browser'), 'all']);
                                  })
                                  ->when($this->adType == 'images', function ($q) {
                                      $q->with([
                                          'cpaBanners' => function ($q) {
                                              $q->whereHas('adSize', function ($q) {
                                                  $q->where('size', '=',
                                                      $this->width . 'x' . $this->height);
                                              });
                                          }
                                      ]);
                                  })
                                  ->when($this->adType == 'contextuals', function ($q) {
                                      $q->whereHas('adSize', function ($q) {
                                          $q->where('size', '=',
                                              $this->width . 'x' . $this->height);
                                      });
                                  })
                                  ->when($this->adType == 'urls', function ($q) {
                                      $q->doesnthave('cpaBanners');
                                  })
                                  ->when($this->adType == 'snippets', function ($q) {
                                      $q->doesnthave('adSize');
                                  });
                            }
                        ]);
                    }
                ]);

Also, am I correct that once Installing Lada, I should remove all calls to "Cache::remember()" in my controllers for it to work as intended?

Thank you! :) 👍

With MongoDB

How To Use This If i Using Jens MongoDB on Laravel ?

can i modified and extends Jens MongoDB Class Model To src/Spiritix/LadaCache/Database/Model only or i modified too all of in this folder src/Spiritix/LadaCache/Database/ ?

sample src/Spiritix/LadaCache/Database/Model.php
`

* @license MIT * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Spiritix\LadaCache\Database; use Illuminate\Database\Eloquent\Model as EloquentModel; /** * Overrides Laravel's model class. * * If Laravel would not have hardcoded the query builder class, this file would not be required anymore. * It would also not be required to have all models extending this class. * * @Package Spiritix\LadaCache\Database * @author Matthias Isler */ class Model extends EloquentModel { /** * Get a new query builder instance for the connection. * * @return \Illuminate\Database\Query\Builder */ protected function newBaseQueryBuilder() { $conn = $this->getConnection(); $grammar = $conn->getQueryGrammar(); return new QueryBuilder( $conn, $grammar, $conn->getPostProcessor(), app()->make('lada.handler') ); } } ` sorry for my bad english thnks

Cache Invalidation not working in Eloquent Relationship belongsToMany

I have observed that though Lada-cache works for the most part, when it comes to eloquent relationships, the cache invalidation doesn't seem to work as expected.

For example:
$this->belongsToMany('App\Models\TableClass1','TableClass2','table_class1_id','table_class2_id');

The above relationship is cached properly during all the read operations for TableClass1, but if any row of TableClass1 or TableClass2 is modified, it purges the cache for the subsequent relationship for all rows of TableClass1/2.

The problem is very much similar to as reported in Issue #11 ( Just that this time its related to eloquent relationship).

1.2 version has issue with Model::firstOrNew

In the new 1.2 version there seems to be a problem with Model::firstOrNew function which somehow bypasses the lada-cache QueryModel

[Symfony\Component\Debug\Exception\FatalThrowableError]
Type error: Argument 4 passed to Spiritix\LadaCache\Database\QueryBuilder::__construct() must be an instance of Spiritix\LadaCache\QueryHandler, none given, called in /home/vagrant/www/panacea/vendor/l
aravel/framework/src/Illuminate/Database/Query/Builder.php on line 2070

Can we have traits for lada-cache

Can we have traits instead of all models extending the Spiritix\LadaCache\Database\Model class? It would make more sense if lada-cache going forward uses traits for peaceful co-existence with other classes.

Problem with cache invalidation

Let's say I have an article table with 100k articles and 100 of those articles are being opened constantly every second so I would need to cache each of those articles. So far so good.
But once I update one article all of the caches for other articles are purged even though I only need the cache for the specific article that I changed to be purged.

I debugged a bit and saw that :table:article:row:28 is being invalidated and also :table:article and I'm guessing that invalidating :table:article tag causes the issue?

If I set considerTables = false in Tagger.php then cache doesn't seem to be invalidated at all even though there still is the :table:article:row:28 tag

Caching relations

I have a model (table) companies

id (index key), companyname, address, phone

I also have a model (table) categories

id (index key), category

this relation is many to many, companies may have many categories and one category may have many companies. For that reason I created a table companies_categories

id_company (index key), id_category (index key)

My question is if lada cache with the current logic will cache everything included the relation with row invalidation? As you see I have assigned both tables with primary key "id" but the relation table has no "id" and I am not sure how this will work.

Tag keys are not prefixed before invalidation

If you debug here:

$this->deleteItems($tags);

you can see that tags are not prefixed with the lada: prefix

output from redis-cli monitor

1474295382.561930 [2 127.0.0.1:57456] "EXISTS" "lada:tags:database:receptes:table:taxonomy_group"
1474295382.567505 [2 127.0.0.1:57456] "SMEMBERS" "lada:tags:database:receptes:table:taxonomy_group"
1474295382.567958 [2 127.0.0.1:57456] "EXISTS" "lada:tags:database:receptes:table:taxonomy_group:row:6"
1474295382.568279 [2 127.0.0.1:57456] "SMEMBERS" "lada:tags:database:receptes:table:taxonomy_group:row:6"
1474295382.572728 [2 127.0.0.1:57456] "DEL" "lada:ca4f3478a25b1a65e6ba63b3d486464b"
1474295382.573023 [2 127.0.0.1:57456] "DEL" "lada:8878cfb82fadfd146ec585caa3b9df35"
1474295382.573387 [2 127.0.0.1:57456] "DEL" "lada:239982319ac7e7e3bde82a09befe8db7"
1474295382.573605 [2 127.0.0.1:57456] "DEL" "tags:database:receptes:table:taxonomy_group"
1474295382.573867 [2 127.0.0.1:57456] "DEL" "tags:database:receptes:table:taxonomy_group:row:6"

Debug bar marks all cache requests as hit

The cache is working properly, but something must be wrong with the debug bar collector. It marks all cache requests as [Hit], even right after the cache is flushed.

LadaCache breaks selectSub method

Hi

Using Model::selectSub($subQuery, 'foo') doesn't work using LadaCacheTrait

The error is

Argument 1 passed to Spiritix\LadaCache\QueryHandler::setBuilder() must be an instance of Spiritix\LadaCache\Database\QueryBuilder, instance of Illuminate\Database\Query\Builder given, called in D:\Progetti\laravel-vivicity\vendor\spiritix\lada-cache\src\Spiritix\LadaCache\Database\QueryBuilder.php on line 94

Test with Laravel 5.2

Currently the library is written for 5.1 LTS.
Test if everything works well with 5.2.

If backwards incompatible changes are required to get it running, create a new repository for 5.2.

ServiceProvider class_exists Error for DebugBar

In the service provider on line 57:

if (class_exists('Barryvdh\\Debugbar\\LaravelDebugbar')) {
    $this->registerDebugbarCollector();
}

This throws major errors if you have DebugBar installed but not enabled.

I had to create my own provider and check the container for debugbar:

if ($this->app->offsetExists('debugbar')) {
    $this->registerDebugbarCollector();
}

would be a much better solution.

Or simply make registerDebugbarCollector() public so it can be overloaded.

Have some question.

Why Lada Cache require php 5.6?
Laravel 5.2 require php 5.5.9 so I think if Lada Cache can require same php as laravel. It's will make another people can use this library easier.

Do you have plan to make it as traits?
I think traits is better more than extend class and user can use it easier.

Expiration time

What is the default expiration time and is it possible to specify custom expiration time?

Let's say I need a list of 10 latest articles whose publish date is less than current time

Example
Article::where('published_at', '<', \DB::raw('now()'))->orderBy('published_at', 'desc')->paginate(10)

It would be great if it would be possible to set how long to cache this query, since displaying articles depends on the current time and we wouldn't want the query to be cached longer than 2 minutes

I guess the problem could be solved by creating a cron that polls the database every minute and finds all the articles whose published_at is less than current time and is_visible is 0 and sets it to 1 and then in the pagination query we just try to find all articles whose is_visible is 1, but I'm not sure if this would be the best or simplest approach instead of just setting a small expiration time for query.

Tests for commands are not working

Unfortunately it seems like orchestral/testbench is not able to handle Artisan commands in unit tests.
It provides the method $this->artisan(...), but always throws an exception.

Possibility to only cache specific models

Not working at the moment.

It would result in all models getting cached but not invalidated properly. This is because the class who writes values in the cache doesn't know which models are extending the cache model.

Also I am not sure what would happen if you join a model that is cached from a model which is not cached.

Add locking mechanism limitation to readme

Using locking mechanisms requires usage of raw sql queries to bypass Lada Cache.
https://laravel.com/docs/5.6/queries#pessimistic-locking

I'm using lockForUpdate, but it obviously won't work if there is caching in-between, because it is not possible to tell the DB to lock something if we never even reached the DB right? 😸
The solution is simply resort to raw query i.e. using the \DB::xxx statements.

Here is an example that I use to bypass Lada Cache and then transform result array back into model object:

        $table = (new YourAmazingModel())->getTable();

        $items = \DB::table($table)
            ->lockForUpdate()
            ->where(' ... filter results ... ')
            ->orderBy('id', 'asc')
            ->take(15)
            ->get();

        // Transform array to YourAmazingModel
        foreach ($items as $key => $item) {
            $items[$key] = (new YourAmazingModel())->newFromBuilder((array)$item);
        }

        $items = collect($items);

        // Now you can loop $items and update them as necessary to release the row locks

Note: Do not forget to wrap your code in transaction so that you can revert the lock in case of exception and avoid deadlocks.

Nested queries whereHas & where doesn't invalidate the many query

Hello,

I am trying to fetch customers that billing_details.collective_bill = true. So at the first time the query gets cached everything works fine but if i enable or disable a customers billing_details.collective_bill the relation gets invalidated but it isn't updated or invalidating the query below. So i am getting the cached results.

Customer::with([
            'billing_details.accounting_period',
            'latest_collective_invoice' => function ($query) {
                $query->select(['id', 'client_id', 'customer_id', 'created_at']);
            },
            'orders_interpret' => function ($query) {
                $query->select(['id', 'customer_id', 'status_id'])
                    ->with(['invoice'])
                    ->withoutInvoice(OrderStatusType::CollectiveInvoice);
            },
            'orders_translate' => function ($query) {
                $query->select(['id', 'customer_id', 'status_id'])
                    ->with(['invoice'])
                    ->withoutInvoice(OrderStatusType::CollectiveInvoice);
            }
        ])
            ->whereHas('billing_details', function ($query) {
                $query->where('collective_bill', true);
            })
            ->where(function ($query) {
                $query->where(function ($query) {
                    $query->whereHas('orders_interpret', function ($query) {
                        $query->withoutInvoice(OrderStatusType::CollectiveInvoice);
                    });
                })
                    ->orWhere(function ($query) {
                        $query->whereHas('orders_translate', function ($query) {
                            $query->withoutInvoice(OrderStatusType::CollectiveInvoice);
                        });
                    });
            })
            ->get();

problem with config merge

this error broke my site on production, when i have cache for compiled classes, and every time LadaCacheServiceProvider do call to:

 protected function mergeConfigFrom($path, $key)
    {
        $config = $this->app['config']->get($key, []);

        $this->app['config']->set($key, array_merge(require $path, $config));
    }

there is error what i got:

ErrorException: Exception 'ErrorException' with message 'array_merge(): Argument #2 is not an array' in /var/app/current/bootstrap/cache/compiled.php:4967

Sample stack trace
in Illuminate\Foundation\Bootstrap\HandleExceptions::handleError called at ? (?)
in array_merge called at /var/app/current/bootstrap/cache/compiled.php (4967)
…vendor/spiritix/lada-cache/src/Spiritix/LadaCache/
LadaCacheServiceProvider.php (55)
in Spiritix\LadaCache\LadaCacheServiceProvider::boot called at ? (?)
in call_user_func_array called at /var/app/current/bootstrap/cache/compiled.php (1187)
…tainer\Container::call called at /var/app/current/bootstrap/cache/
compiled.php (1808)
…lication::bootProvider called at /var/app/current/bootstrap/cache/
compiled.php (1800)
in Illuminate\Foundation\Application::Illuminate\Foundation\{closure} called at ? (?)
in array_walk called at /var/app/current/bootstrap/cache/compiled.php (1801)
…tion\Application::boot called at /var/app/current/bootstrap/cache/
compiled.php (2139)
…otProviders::bootstrap called at /var/app/current/bootstrap/cache/
compiled.php (1587)
…ication::bootstrapWith called at /var/app/current/bootstrap/cache/
compiled.php (2303)
…Http\Kernel::bootstrap called at /var/app/current/bootstrap/cache/
compiled.php (2256)
…ndRequestThroughRouter called at /var/app/current/bootstrap/cache/
compiled.php (2240)
…ate\Foundation\Http\Kernel::handle called at /var/app/current/public/
index.php (55)

Problem with caching

I have a problem. At some point of time the cache of the following request ceases to be updated for the unknown reasons.

$newProducts = $product->catalogItem()
->whereNotNull('available')
->whereNull('preorder')
->orderBy('release_date', 'desc')
->limit($limitProductsOnTabs)
->get();

public function scopeCatalogItem($query)
{
return $query->select('products.id', 'image', 'name', 'rrp', 'wmr', 'activation_id', 'slug', 'has_discount', getNameCurr())->with('activation')->with('genres');
}

But the page of product is successfully cached. Why?

Working for shared hosting (Question)

Is this working for shared hosting? As i known redis is not working. Redis want your own server. I am looking to implement a cache system all of our project. Thanks in advance.

i get BadMethodCallException when i disable lada

when i dont want lada
i run the artisan command to disable it and it told me
Cache disabled
but when i changed to file cache this appears
BadMethodCallException in Repository.php line 367:
This cache store does not support tagging.

Write functional tests

It would be great to have sample queries for all cases and have them tested automatically.

Illegal offset type in isset or empty

The above error is thrown when using Laravel 5.7 Sub-Query Joins

$payments = Payment::groupBy('file_id');

    $files = File::join('clients', function ($join) {
        $join->on('clients.id', '=', 'files.client_id')
            ->where('clients.active', 1)
            ->whereNull('deleted_at');
    })->leftJoinSub($payments, 'payments', function ($join) {
        $join->on('files.id', '=', 'payments.file_id');
    })->select('files.*')
        ->addSelect(DB::raw('SUM(payments.amount) as total_paid'))
        ->take(10)
        ->get();

    dump($files);

Any way to deal with this?

Laravel 5.4

Just tried to install with 5.4, and getting this error from composer require:

...
> php artisan optimize

  [Symfony\Component\Debug\Exception\FatalThrowableError]
  Call to undefined method Illuminate\Foundation\Application::share()

Script php artisan optimize handling the post-update-cmd event returned with error code 1

Does lada-cache support 5.4?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.