Nestjs how to clear ( reset ) all cache - javascript

I'm building an API and the data get updated every day at 3 am and need to clear all cached endpoints whatever is!
I'm using the CacheModule and the decorator #UserInterceptor(CacheInterceptor) to cache whatever I need in the controller.
there a Cron function that runs every day at 3 am to update the content, I need to know what the code should put in that method to clear all cache.

You can inject the underlying cache manager instance:
constructor(#Inject(CACHE_MANAGER) protected readonly cacheManager) {}
And then use it to delete the caches for all keys:
const keys = await this.cacheManager.keys()
await this.cacheManager.del(keys)

According to the official NestJs docs (July 2022), they offer a .reset() method to "clear the entire cache". This examples assumes you're using the naming convention in their docs, where cacheManager is the locally scoped & injected CACHE_MANAGER from #nestjs/common and "Cache" from cache-manager package.
// inside the class constructor
constructor(#Inject(CACHE_MANAGER) private cacheManager: Cache) {}
// and then inside a class method
await this.cacheManager.reset();
Reference: https://docs.nestjs.com/techniques/caching

Related

lb4 call another repository in different repository

What is the best way of calling different repository at the main repository? I tried to use Services. For example
...
#injectable({scope: BindingScope.TRANSIENT})
export class ProjectService {
constructor(#repository(ProjectRepository) public projectRepository: ProjectRepository) { }
}
Here is my service code. When I define this service at another repoository, I am able to access projectRepository. But I am not sure this is the best way.
We can take a page from Relations [1] and utilize #repository.getter() [2] to perform dependency injection in the main Repository:
import {Getter} from '#loopback/core';
import {DefaultCrudRepository, repository} from '#loopback/repository';
export class MainRepository() extends DefaultCrudRepository</*...*/>{
constructor(
#repository.getter(ProjectRepository)
private _projectRepositoryGetter: Getter<ProjectRepository>;
)
async yourFunction(): Promise<void> {
let projectRepository = await this._projectRepositoryGetter();
// `projectRepository` now contains an instance of ProjectRepository.
}
}
In the example above, we're utilizing constructor injection and retrieving the ProjectRepository instance in an arbitrary function called yourFunction. However, you can use any flavour of dependency injection [3] and retrieve the instance in any function within the same closure.
Why getters?
Getters to prevent circular dependencies. These are especially prevalent in Repositories as they may have Relations that interconnect between each other. Getters achieve this by delaying the binding resolution until explicitly requested by the LB4 application.
When to use Services?
Services can be considered a higher-level abstract than Repositories. They aren't expected to implement a standard CRUD or KV interface and aren't assumed to be linked to a DataSource. This is useful if you need logic that are out-of-scope of Repositories. For example, a Service may implement a function that adds a new database record and uploads a file to Amazon S3. This keeps a clear separation between the code that interfaces with the Datastore and those that don't, thereby ensuring that the Datastore logic is kept predictable, readable and easy to test.
Links
[1] https://loopback.io/doc/en/lb4/HasMany-relation.html#configuring-a-hasmany-relation (archive)
[2] https://loopback.io/doc/en/lb4/apidocs.repository.repository.getter.html (git permalink)
[3] https://loopback.io/doc/en/lb4/Dependency-injection.html#flavors-of-dependency-injection (git permalink)

Access the request object from Express inside a Mongoose Plugin

I have an API in ExpressJS and a middleware that gets executed before each endpoint controller:
app.use(segregationMiddleware);
app.get('/some-endpoint', controller1);
app.get('/some-endpoint-2', controller2);
The segregationMiddleware is used to look for some parameters in the request and then it calculates a value that then is stored in the request object as req.locals.domain so the controllers can access it.
In each Mongoose model, I define a field named domain using a Mongoose plugin (so I don't have to do it every time). That field is used to segregate my assets. This means that when the segregationMiddleware populates req.locals.domain = 'foo' for example, if I make a model.find({}) I want to get only assets that have { domain: 'foo' }. Same thing if I try to update, save, delete, and so.
Of course, I can just simply modify the query on each controller since I have accesso to req, but I need to do it every time and I need to remember it for finds, findAndUpdate, save, and soo... sooner or later I'm gonna forget it.
I can define some hooks in Mongoose that will modify the query using a plugin so it adds the domain constraint to the query so I don't have to do it in the controller BUT I don't have the current req object in the Mongoose plugin unless I pass it, and the only way that come to my mind is to abstract the DB methods in the plugin, so in the controller, I do something like this:
model.safeFind(req, query);
And in the plugin I define safeFind like:
safeFind = () => {
const theRealQuery = Object.assign({}, query, { domain: req.locals.domain });
return this.find(query);
}
BUT, in this way, I need to redefine each DB query function (find, findOne, update, save...) and I need to remember to use the safe methods. Then again, I'm going to forget it sooner or later.
Is there a way I can still use the regular Mongoose methods from the controller and have the plugin somehow modify the query for every method using the current req object?

Proper way to bind to data object in Angular 2 service?

I am building an angular 2 application. The documentation has changed quite a bit since the released which has caused confusion. The best I can do is explain what I am trying to do (Which was easy in Angular 1) and hope someone can help me out.
I have created a login service using JWT's.
Once login is successful, I return a user object.
I have a loginComponent ( binds data to template ) and loginService ( which handles the https calls )
I have a userService which maintains the user object.
I have a userComponent which renders the user data.
The problem is, once the user has logged in, I am unclear on the best approach for letting the userService retrieve the new data in an object called "user", then the userComponent update its user object on the template. This was easy in angular 1 simply by putting a watcher on the userService.user object.
I tried Inputs and Outputs to no avail, eventEmitters, Observables and getters and setters. The getters and setters work, but force me to store everything in a "val()"
Can someone please tell me the best way to achieve this?
User Component renders template with user.firstName, user.lastName etc.
Initially user if an empty Object
The login service needs to set the UserService.user
The userComponent Needs to detect the change and update the DOM.
Thanks in ADVANCE!
If I'm not wrong, you are looking for a way to 'listen' to changes in your UserService.user to make appropriate updates in your UserComponent. It is fairly easy to do that with Subject (or BehaviorSubject).
-In your UserService, declare a property user with type Subject<User>.
user: Subject<User> = new Subject();
-Expose it to outside as observable:
user$: Observable<User>
...
this.user$ = this.user.asObservable();
-Login function will update the private user Subject.
login(userName: string, password: string) {
//...
this.user.next(new User("First name", "Last name"));
}
-In your UserComponent, subscribe to UserServive's user$ observable to update view.
this.userService.user$.subscribe((userData) => {this.user = userData;});
-In your view, simply use string interpolation:
{{user?.firstName}} {{user?.lastName}}
Here is the working plunker: http://plnkr.co/edit/qUR0spZL9hgZkBe8PHw4?p=preview
There are two rather different approaches you could take:
1. Share data via JavaScript reference types
If you create an object in your UserService
#Injectable()
export class UserService {
public user = new User();
you can then share that object just by virtue of it being a JavaScript reference type. Any other service or component that injects the UserService will have access to that user object. As long as you only modify the original object (i.e., you don't assign a new object) in your service,
updateUser(user:User) {
this.user.firstName = user.firstName;
this.user.lastName = user.lastName;
}
all of your views will automatically update and show the new data after it is changed (because of the way Angular change detection works). There is no need for any Angular 1-like watchers.
Here's an example plunker.
In the plunker, instead of a shared user object, it has a shared data object. There is a change data button that you can click that will call a changeData() method on the service. You can see that the AppComponent's view automatically updates when the service changes its data property. You don't have to write any code to make this work -- no getter, setter, Input, Output/EventEmitter, or Observable is required.
The view update automatically happens because (by default) Angular change detection checks all of the template bindings (like {{data.prop1}}) each time a monkey-patched asynchronous event fires (such as a button click).
2. "Push" data using RxJS
#HarryNinh covered this pretty well in his answer. See also Cookbook topic Parent and children communicate via a service. It shows how to use a Subject to facilitate communications "within a family".
I would suggest using a BehaviorSubject instead of a Subject because a BehaviorSubject has the notion of "the current value", which is likely applicable here. Consider, if you use routing and (based on some user action) you move to a new route and create a new component, you might want that new component to be able check the "current value" of the user. You'll need a BehaviorSubject to make that work. If you use a regular Subject, the new component will have no way to retrieve the current value, since subscribers to a Subject can only get newly emitted values.
So, should we use approach 1. or 2.? As usual, "it depends". Approach 1. is a lot less code, and you don't need to understand RxJS (but you do need to understand JavaScript reference types). Approach 2. is all the rage these days.
Approach 2. could also be more efficient than 1., but because Angular's default change detection strategy is to "check all components", you would need to use the OnPush change detection strategy and markForCheck() (I'm not going to get into how to use those here) to make it more efficient than approach 1.

Private variables in Ember-data DS.Model

I want to store a private variable on each DS.Model. Its purpose is to store a pending callback (in case I want to cancel it).
I have tried this (and it works):
DS.Model.reopen({
init() {
let _pending; // my private var
this._getPending = () => _pending; // get private var
this._setPending = callback => _pending = callback; // set private var
this._super(...arguments);
}
});
I have placed this in an initializer, and it works as I expect it to.
My questions are: Is this a good practise? is it likely to mess anything up? ...and, is there a better way?
Personally, I'm happy with the way it works.. but I'm not sure if its the "Ember" way. This is going to go into an Ember-cli addon, so I would like it to be the most "best practise" as possible. (the _getPending/_setPending method are only to be used internally within the addon.)
Here are my 2 cents on this. I would say no it is not a good practice, but it should be okay since they are just Ember Objects. The question here is what is Ember data model used for? From doc it says:
"Models are objects that represent the underlying data that your application presents to the user."
By definition this is not what they are designed for, so just because you are able to it does not mean that you should use them like this.
Pending callback so it can be canceled? Ember model API has defined state objects that can be used for this purpose. http://emberjs.com/api/data/classes/DS.Model.html Flags like isDeleted, isValid, isNew...gives all possible state.
I would place them in router actions where they are easy tested with integration tests.
You can check this screencast that explains them:
https://www.emberscreencasts.com/posts/102-ember-data-20-model-states-and-flags
Hope it helps.

How to inject state parameter automatically

Abstract
Hi, I'm using angular + ui-router in my project, I have huge amount of nested states and different views that in turn contain huge amount of different inputs, a user fills these inputs incrementally step by step.
The problem
Sometimes users require additional info that is located on the previous step, and browsers "back" button helps the user to sneak peek into that data, but as soon as the user presses it, the info he already entered is lost due to state transition, which is obviously a bad thing.
Strategy
In order to overcome described problem I have the following plan:
Associate each user's "navigation" (guess this is a proper term) with a random id
To prevent scope-inheritance-and-serialization issues, instead of putting viewmodel into $scope use ordinary javascript object that will be storing immediate values that are bound to UI.
Add watcher to look for changes on that "storage object"
As soon as the change spotted, serialize the object and persist it
Explanations
Why do we need a random parameter in URL?
We don't want to store all data in URL, since there might be quite some amount of data that wont fit into URL. So in order to provide the guarantees the URL won't break, we put only small random GUID/UUID into it that later allows obtaining the data associated with current "navigation" by this random GUID/UUID.
The storage
There are multitude of storage scenarios available out there: LocalStorage, IndexedDB, WebSQL, Session Storage, you name it, but due to their cross-tab, cross-browser, browser-specific nature it would be hard to manipulate and manage all of the data that gets into the storage. The implementation will be buggy / might require server-side support.
So the most elegant storage strategy for this scenario would be storing data in special window.name variable which is capable of storing data in-between requests. So the data is safe until you close your tab.
The Question
On behalf of everything written above, I have the root view called "view" that has a state parameter id (this is the random GUID/UUID)
$stateProvider.state('view', {
url: '/view/{id}',
controller: 'view',
templateUrl: 'views/view.html'
});
All of the other views derive from this view, is there way to make ui-sref directive to automatically inject a random GUID/UUID into id state parameter of my root view, instead of writing each time ui-sref's like:
<a ui-sref="view({id:guid()}).someNestedView({someNestedParam: getParam()})"
I would like to have something like:
<a ui-sref="view.someNestedView({someNestedParam: getParam()})"
The AOP and Decorator pattern are the answer. The comprehensive description could be found here:
Experiment: Decorating Directives by Jesus Rodriguez
Similar solution as described below, could be observed:
Changing the default behavior of $state.go() in ui.router to reload by default
How that would work? There is a link to working example
In this case, we do not solve from which source the random GUID comes from. Let's just have it in runtime:
var guidFromSomeSource = '70F81249-2487-47B8-9ADF-603F796FF999';
Now, we can inject an Decorator like this:
angular
.module('MyApp')
.config(function ($provide) {
$provide.decorator('$state', function ($delegate) {
// let's locally use 'state' name
var state = $delegate;
// let's extend this object with new function
// 'baseGo', which in fact, will keep the reference
// to the original 'go' function
state.baseGo = state.go;
// here comes our new 'go' decoration
var go = function (to, params, options) {
params = params || {};
// only in case of missing 'id'
// append our random/constant 'GUID'
if (angular.isUndefined(params.id)) {
params.id = guidFromSomeSource;
}
// return processing to the 'baseGo' - original
this.baseGo(to, params, options);
};
// assign new 'go', right now decorating the old 'go'
state.go = go;
return $delegate;
});
})
Code should be self explanatory, check it in action here

Categories

Resources