MOBILE-3188 Web services: Record component that owns WS cache item
This commit adds optional component and componentId fields to the preSets variable, which are recorded in the wscache table. These are then used by (a) core site plugins where a module cmid is available, and (b) the forum (as an example core implementation) so that module site plugins and forum provide the new data. (Note that this is not going to be very useful where we retrieve data for multiple activities at once, which happens for activities like Page. Still, it is optional.)main
parent
b67ea14abb
commit
d0c93f6416
|
@ -354,7 +354,8 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
|
|||
this.page = 0;
|
||||
}
|
||||
|
||||
return this.forumProvider.getDiscussions(this.forum.id, this.selectedSortOrder.value, this.page).then((response) => {
|
||||
return this.forumProvider.getDiscussions(this.forum.id, this.forum.cmid,
|
||||
this.selectedSortOrder.value, this.page).then((response) => {
|
||||
let promise;
|
||||
if (this.usesGroups) {
|
||||
promise = this.forumProvider.formatDiscussionsGroups(this.forum.cmid, response.discussions);
|
||||
|
|
|
@ -323,7 +323,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
let ratingInfo;
|
||||
|
||||
return syncPromise.then(() => {
|
||||
return this.forumProvider.getDiscussionPosts(this.discussionId).then((response) => {
|
||||
return this.forumProvider.getDiscussionPosts(this.discussionId, this.cmId).then((response) => {
|
||||
onlinePosts = response.posts;
|
||||
ratingInfo = response.ratinginfo;
|
||||
}).then(() => {
|
||||
|
@ -412,7 +412,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
|
||||
// The discussion object was not passed as parameter and there is no starting post. Should not happen.
|
||||
if (!this.discussion) {
|
||||
promises.push(this.loadDiscussion(this.forumId, this.discussionId));
|
||||
promises.push(this.loadDiscussion(this.forumId, this.cmId, this.discussionId));
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
|
@ -479,13 +479,14 @@ export class AddonModForumDiscussionPage implements OnDestroy {
|
|||
* Convenience function to load discussion.
|
||||
*
|
||||
* @param forumId Forum ID.
|
||||
* @param cmId Forum cmid.
|
||||
* @param discussionId Discussion ID.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected loadDiscussion(forumId: number, discussionId: number): Promise<void> {
|
||||
protected loadDiscussion(forumId: number, cmId: number, discussionId: number): Promise<void> {
|
||||
// Fetch the discussion if not passed as parameter.
|
||||
if (!this.discussion && forumId) {
|
||||
return this.forumHelper.getDiscussionById(forumId, discussionId).then((discussion) => {
|
||||
return this.forumHelper.getDiscussionById(forumId, cmId, discussionId).then((discussion) => {
|
||||
this.discussion = discussion;
|
||||
this.discussionId = this.discussion.discussion;
|
||||
}).catch(() => {
|
||||
|
|
|
@ -492,15 +492,18 @@ export class AddonModForumProvider {
|
|||
* Get forum discussion posts.
|
||||
*
|
||||
* @param discussionId Discussion ID.
|
||||
* @param cmId Forum cmid.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with forum posts and rating info.
|
||||
*/
|
||||
getDiscussionPosts(discussionId: number, siteId?: string): Promise<{posts: any[], ratinginfo?: CoreRatingInfo}> {
|
||||
getDiscussionPosts(discussionId: number, cmId: number, siteId?: string): Promise<{posts: any[], ratinginfo?: CoreRatingInfo}> {
|
||||
const params = {
|
||||
discussionid: discussionId
|
||||
};
|
||||
const preSets = {
|
||||
cacheKey: this.getDiscussionPostsCacheKey(discussionId)
|
||||
cacheKey: this.getDiscussionPostsCacheKey(discussionId),
|
||||
component: AddonModForumProvider.COMPONENT,
|
||||
componentId: cmId
|
||||
};
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -592,6 +595,7 @@ export class AddonModForumProvider {
|
|||
* Get forum discussions.
|
||||
*
|
||||
* @param forumId Forum ID.
|
||||
* @param cmId Forum cmid
|
||||
* @param sortOrder Sort order.
|
||||
* @param page Page.
|
||||
* @param forceCache True to always get the value from cache. false otherwise.
|
||||
|
@ -601,7 +605,8 @@ export class AddonModForumProvider {
|
|||
* discussion ID is discussion.discussion.
|
||||
* - canLoadMore: True if there may be more discussions to load.
|
||||
*/
|
||||
getDiscussions(forumId: number, sortOrder?: number, page: number = 0, forceCache?: boolean, siteId?: string): Promise<any> {
|
||||
getDiscussions(forumId: number, cmId: number, sortOrder?: number, page: number = 0,
|
||||
forceCache?: boolean, siteId?: string): Promise<any> {
|
||||
sortOrder = sortOrder || AddonModForumProvider.SORTORDER_LASTPOST_DESC;
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
@ -626,7 +631,9 @@ export class AddonModForumProvider {
|
|||
}
|
||||
}
|
||||
const preSets: CoreSiteWSPreSets = {
|
||||
cacheKey: this.getDiscussionsListCacheKey(forumId, sortOrder)
|
||||
cacheKey: this.getDiscussionsListCacheKey(forumId, sortOrder),
|
||||
component: AddonModForumProvider.COMPONENT,
|
||||
componentId: cmId
|
||||
};
|
||||
if (forceCache) {
|
||||
preSets.omitExpires = true;
|
||||
|
@ -673,6 +680,7 @@ export class AddonModForumProvider {
|
|||
* If a page fails, the discussions until that page will be returned along with a flag indicating an error occurred.
|
||||
*
|
||||
* @param forumId Forum ID.
|
||||
* @param cmId Forum cmid.
|
||||
* @param sortOrder Sort order.
|
||||
* @param forceCache True to always get the value from cache, false otherwise.
|
||||
* @param numPages Number of pages to get. If not defined, all pages.
|
||||
|
@ -682,8 +690,8 @@ export class AddonModForumProvider {
|
|||
* - discussions: List of discussions.
|
||||
* - error: True if an error occurred, false otherwise.
|
||||
*/
|
||||
getDiscussionsInPages(forumId: number, sortOrder?: number, forceCache?: boolean, numPages?: number, startPage?: number,
|
||||
siteId?: string): Promise<any> {
|
||||
getDiscussionsInPages(forumId: number, cmId: number, sortOrder?: number, forceCache?: boolean,
|
||||
numPages?: number, startPage?: number, siteId?: string): Promise<any> {
|
||||
if (typeof numPages == 'undefined') {
|
||||
numPages = -1;
|
||||
}
|
||||
|
@ -700,7 +708,7 @@ export class AddonModForumProvider {
|
|||
|
||||
const getPage = (page: number): Promise<any> => {
|
||||
// Get page discussions.
|
||||
return this.getDiscussions(forumId, sortOrder, page, forceCache, siteId).then((response) => {
|
||||
return this.getDiscussions(forumId, cmId, sortOrder, page, forceCache, siteId).then((response) => {
|
||||
result.discussions = result.discussions.concat(response.discussions);
|
||||
numPages--;
|
||||
|
||||
|
@ -753,7 +761,7 @@ export class AddonModForumProvider {
|
|||
|
||||
this.getAvailableSortOrders().forEach((sortOrder) => {
|
||||
// We need to get the list of discussions to be able to invalidate their posts.
|
||||
promises.push(this.getDiscussionsInPages(forum.id, sortOrder.value, true).then((response) => {
|
||||
promises.push(this.getDiscussionsInPages(forum.id, forum.cmid, sortOrder.value, true).then((response) => {
|
||||
// Now invalidate the WS calls.
|
||||
const promises = [];
|
||||
|
||||
|
|
|
@ -270,15 +270,16 @@ export class AddonModForumHelperProvider {
|
|||
* This function is inefficient because it needs to fetch all discussion pages in the worst case.
|
||||
*
|
||||
* @param forumId Forum ID.
|
||||
* @param cmId Forum cmid
|
||||
* @param discussionId Discussion ID.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with the discussion data.
|
||||
*/
|
||||
getDiscussionById(forumId: number, discussionId: number, siteId?: string): Promise<any> {
|
||||
getDiscussionById(forumId: number, cmId: number, discussionId: number, siteId?: string): Promise<any> {
|
||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||
|
||||
const findDiscussion = (page: number): Promise<any> => {
|
||||
return this.forumProvider.getDiscussions(forumId, undefined, page, false, siteId).then((response) => {
|
||||
return this.forumProvider.getDiscussions(forumId, cmId, undefined, page, false, siteId).then((response) => {
|
||||
if (response.discussions && response.discussions.length > 0) {
|
||||
// Note that discussion.id is the main post ID but discussion ID is discussion.discussion.
|
||||
const discussion = response.discussions.find((discussion) => discussion.discussion == discussionId);
|
||||
|
|
|
@ -114,7 +114,8 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
|
|||
protected getPostsForPrefetch(forum: any, siteId?: string): Promise<any[]> {
|
||||
const promises = this.forumProvider.getAvailableSortOrders().map((sortOrder) => {
|
||||
// Get discussions in first 2 pages.
|
||||
return this.forumProvider.getDiscussionsInPages(forum.id, sortOrder.value, false, 2, 0, siteId).then((response) => {
|
||||
return this.forumProvider.getDiscussionsInPages(forum.id, forum.cmid,
|
||||
sortOrder.value, false, 2, 0, siteId).then((response) => {
|
||||
if (response.error) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
@ -122,7 +123,7 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
|
|||
const promises = [];
|
||||
|
||||
response.discussions.forEach((discussion) => {
|
||||
promises.push(this.forumProvider.getDiscussionPosts(discussion.discussion, siteId));
|
||||
promises.push(this.forumProvider.getDiscussionPosts(discussion.discussion, forum.cmid, siteId));
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
|
|
|
@ -127,6 +127,17 @@ export interface CoreSiteWSPreSets {
|
|||
* Defaults to CoreSite.FREQUENCY_USUALLY.
|
||||
*/
|
||||
updateFrequency?: number;
|
||||
|
||||
/**
|
||||
* Component name. Optionally included if this request is being made on behalf of a specific
|
||||
* component (e.g. activity).
|
||||
*/
|
||||
component?: string;
|
||||
|
||||
/**
|
||||
* Component id. Optionally included when 'component' is set.
|
||||
*/
|
||||
componentId?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,7 +208,7 @@ export class CoreSite {
|
|||
protected wsProvider: CoreWSProvider;
|
||||
|
||||
// Variables for the database.
|
||||
static WS_CACHE_TABLE = 'wscache';
|
||||
static WS_CACHE_TABLE = 'ws_cache';
|
||||
static CONFIG_TABLE = 'core_site_config';
|
||||
|
||||
// Versions of Moodle releases.
|
||||
|
@ -1128,6 +1139,13 @@ export class CoreSite {
|
|||
entry.key = preSets.cacheKey;
|
||||
}
|
||||
|
||||
if (preSets.component) {
|
||||
entry.component = preSets.component;
|
||||
if (preSets.componentId) {
|
||||
entry.componentId = preSets.componentId;
|
||||
}
|
||||
}
|
||||
|
||||
return this.db.insertRecord(CoreSite.WS_CACHE_TABLE, entry);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
</core-context-menu>
|
||||
</core-navbar-buttons>
|
||||
|
||||
<core-site-plugins-plugin-content *ngIf="component && method" [component]="component" [method]="method" [args]="args" [initResult]="initResult" [data]="jsData" [pageTitle]="pageTitle" (onContentLoaded)="contentLoaded($event)" (onLoadingContent)="contentLoading($event)"></core-site-plugins-plugin-content>
|
||||
<core-site-plugins-plugin-content *ngIf="component && method" [component]="component" [componentId]="componentId" [method]="method" [args]="args" [initResult]="initResult" [data]="jsData" [pageTitle]="pageTitle" (onContentLoaded)="contentLoaded($event)" (onLoadingContent)="contentLoading($event)"></core-site-plugins-plugin-content>
|
||||
|
|
|
@ -37,6 +37,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
|||
@ViewChild(CoreSitePluginsPluginContentComponent) content: CoreSitePluginsPluginContentComponent;
|
||||
|
||||
component: string;
|
||||
componentId: number;
|
||||
method: string;
|
||||
args: any;
|
||||
initResult: any;
|
||||
|
@ -77,6 +78,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
|||
|
||||
if (handler) {
|
||||
this.component = handler.plugin.component;
|
||||
this.componentId = this.module.id;
|
||||
this.method = handler.handlerSchema.method;
|
||||
this.args = {
|
||||
courseid: this.courseId,
|
||||
|
|
|
@ -32,6 +32,7 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
|||
@ViewChild('compile') compileComponent: ElementRef;
|
||||
|
||||
@Input() component: string;
|
||||
@Input() componentId?: number;
|
||||
@Input() method: string;
|
||||
@Input() args: any;
|
||||
@Input() initResult: any; // Result of the init WS call of the handler.
|
||||
|
@ -92,7 +93,13 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
|
|||
|
||||
this.forceCompile = false;
|
||||
|
||||
return this.sitePluginsProvider.getContent(this.component, this.method, this.args, this.preSets).then((result) => {
|
||||
const preSets = Object.assign({}, this.preSets);
|
||||
preSets.component = this.component;
|
||||
if (this.componentId) {
|
||||
preSets.componentId = this.componentId;
|
||||
}
|
||||
|
||||
return this.sitePluginsProvider.getContent(this.component, this.method, this.args, preSets).then((result) => {
|
||||
this.content = result.templates.length ? result.templates[0].html : ''; // Load first template.
|
||||
this.javascript = result.javascript;
|
||||
this.otherData = result.otherdata;
|
||||
|
|
|
@ -514,7 +514,14 @@ export class CoreSitePluginsProvider {
|
|||
promises.push(this.callWS(method, params, {cacheKey: cacheKey}));
|
||||
} else {
|
||||
// It's a method to get content.
|
||||
promises.push(this.getContent(component, method, args).then((result) => {
|
||||
const preSets = {
|
||||
component: component,
|
||||
componentId: undefined
|
||||
};
|
||||
if (module) {
|
||||
preSets.componentId = module.id;
|
||||
}
|
||||
promises.push(this.getContent(component, method, args, preSets).then((result) => {
|
||||
const subPromises = [];
|
||||
|
||||
// Prefetch the files in the content.
|
||||
|
|
|
@ -360,7 +360,7 @@ export class CoreSitesProvider {
|
|||
// Site schema for this provider.
|
||||
protected siteSchema: CoreSiteSchema = {
|
||||
name: 'CoreSitesProvider',
|
||||
version: 1,
|
||||
version: 2,
|
||||
canBeCleared: [ CoreSite.WS_CACHE_TABLE ],
|
||||
tables: [
|
||||
{
|
||||
|
@ -382,6 +382,14 @@ export class CoreSitesProvider {
|
|||
{
|
||||
name: 'expirationTime',
|
||||
type: 'INTEGER'
|
||||
},
|
||||
{
|
||||
name: 'component',
|
||||
type: 'TEXT'
|
||||
},
|
||||
{
|
||||
name: 'componentId',
|
||||
type: 'INTEGER'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -399,7 +407,27 @@ export class CoreSitesProvider {
|
|||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
async migrate (db: SQLiteDB, oldVersion: number, siteId: string): Promise<any> {
|
||||
if (oldVersion && oldVersion < 2) {
|
||||
const newTable = CoreSite.WS_CACHE_TABLE;
|
||||
const oldTable = 'wscache';
|
||||
|
||||
try {
|
||||
await db.tableExists(oldTable);
|
||||
} catch (error) {
|
||||
// Old table does not exist, ignore.
|
||||
return;
|
||||
}
|
||||
// Cannot use insertRecordsFrom because there are extra fields, so manually code INSERT INTO.
|
||||
await db.execute(
|
||||
'INSERT INTO ' + newTable + ' ' +
|
||||
'SELECT id, data, key, expirationTime, NULL as component, NULL as componentId ' +
|
||||
'FROM ' + oldTable);
|
||||
|
||||
return await db.dropTable(oldTable);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
constructor(logger: CoreLoggerProvider,
|
||||
|
|
Loading…
Reference in New Issue