我正在尝试构建一个小的脚本,可以在Google课堂中添加许多课程。
我正在为此使用C#,并且使用了以下2个引用来使我开始这样做:
https://developers.google.com/classroom/guides/manage-courses
https://developers.google.com/classroom/guides/batch
[当我使用API逐一添加它们时,它确实可以正常工作,没有任何问题,但是,当我尝试使用上面链接中指示的BatchRequest方法时,我开始出错。
首先,假设我要添加一组50个类,当我运行代码时,仅添加了3个或4个类,然后我收到其余的错误消息。
错误仅如下图所示……
我不知道这是怎么回事,我无法理解其原因...
下面是我正在使用的代码:
using Google.Apis.Classroom.v1;
using Google.Apis.Classroom.v1.Data;
using Google.Apis.Requests;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace GSuite_ClassroomManager
{
class Program
{
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/classroom.googleapis.com-dotnet-quickstart.json
static string[] Scopes = { ClassroomService.Scope.ClassroomCourses };
static string ApplicationName = "Classroom API .NET Quickstart";
static void Main(string[] args)
{
//StartMultipleThread();
buildCourses();
}
static void buildCourses()
{
//UserCredential credential;
string Exepath = System.Reflection.Assembly.GetExecutingAssembly().Location;
string currDirectory = System.IO.Path.GetDirectoryName(Exepath);
string jsonFile = currDirectory + @"\credentials.json";
var credential = GoogleCredential.FromFile(jsonFile).CreateScoped(Scopes).CreateWithUser("me");
var courses = new List<Course>();
Console.WriteLine(DateTime.Now.ToString() + " - Authorized successfully...");
// Create Classroom API service.
var service = new ClassroomService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
for (var counter=0; counter < 50; counter++)
{
CourseAlias alias = new CourseAlias
{
Alias = "d:test0018"+counter.ToString()
};
var body = new Course
{
Name = "Test course new 18 "+counter.ToString(),
Id = alias.Alias,
OwnerId = "me",
DescriptionHeading = "Welcome to Test course new " + counter.ToString()+"!",
Description = "This is a testing course number " + counter.ToString(),
CourseState = "ACTIVE"
};
//Console.WriteLine(DateTime.Now.ToString() + " - Creating Test course 3...");
courses.Add(body);
//alias = service.Courses.Aliases.Create(alias, body.Id).Execute();
}
var batch = new BatchRequest(service, "https://classroom.googleapis.com/batch");
BatchRequest.OnResponse<Course> callback = (course,error,i,message) =>
{
if (error != null)
{
Console.WriteLine(DateTime.Now.ToString() + " - Failed to create new course with the following error..: {0}", error.Message);
}
//else
//{
//Console.WriteLine(DateTime.Now.ToString() + " - Created new course: {0} with ID {1}, and alias of {2}...", course.Name, course.Id, course.Id);
//}
};
foreach (var course in courses)
{
var item = new Course
{
Name = course.Name,
Id = course.Id,
OwnerId = course.OwnerId,
DescriptionHeading = course.DescriptionHeading,
Description = course.Description,
CourseState = course.CourseState
};
var result = service.Courses.Create(item);
batch.Queue<Course>(result, callback);
//Console.WriteLine(DateTime.Now.ToString() + " - Created new course: {0} with ID {1}, and alias of {2}...", result.Name, result.Id, course.Id);
}
Task.WaitAll(batch.ExecuteAsync());
Console.WriteLine(DateTime.Now.ToString() + " - Retrieving list of courses");
// Define request parameters.
CoursesResource.ListRequest request = service.Courses.List();
request.PageSize = 100;
// List courses.
ListCoursesResponse response = request.Execute();
Console.WriteLine(DateTime.Now.ToString() + " - Listing courses:");
if (response.Courses != null && response.Courses.Count > 0)
{
foreach (var course in response.Courses)
{
Console.WriteLine("{0} ({1})", course.Name, course.Id);
}
}
else
{
Console.WriteLine(DateTime.Now.ToString() + " - No courses found.");
}
Console.WriteLine(DateTime.Now.ToString() + " - Done.");
Console.Read();
}
}
}
我一直在尝试解决此问题,但是没有得到任何结果。我知道有1000个请求限制,但是我只运行50个,最多只能添加300个课程...
我已获得适当的授权,并且我可以一一使用正常的方法来创建课程,但是如果我不批量使用,那么我拥有的课程很多,它将永远消失...
我可以采取任何措施来排除故障并了解发生了什么吗?
编辑-因此,我更改了代码并使用5个线程进行调用并添加了课程,但是该过程仍然非常缓慢,并且其运行速度似乎就像我只是逐个循环浏览项目...
这是线程的新代码:
static private void buildCourses()
{
//UserCredential credential;
string Exepath = System.Reflection.Assembly.GetExecutingAssembly().Location;
string currDirectory = System.IO.Path.GetDirectoryName(Exepath);
string jsonFile = currDirectory + @"\credentials.json";
var credential = GoogleCredential.FromFile(jsonFile).CreateScoped(Scopes).CreateWithUser("me");
var courses = new List<Course>();
Console.WriteLine(DateTime.Now.ToString() + " - Authorized successfully...");
// Create Classroom API service.
var service = new ClassroomService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
for (var counter=0; counter < 500; counter++)
{
CourseAlias alias = new CourseAlias
{
Alias = "d:test0476"+counter.ToString()
};
var body = new Course
{
Name = "Test course new 476 "+counter.ToString(),
Id = alias.Alias,
OwnerId = "me",
DescriptionHeading = "Welcome to Test course new " + counter.ToString()+"!",
Description = "This is a testing course number " + counter.ToString(),
CourseState = "ACTIVE"
};
courses.Add(body);
}
var itemsCout = courses.Count;
var threadCount = 5;
Thread thread1 = new Thread(() =>
{
Console.WriteLine("Started thread {0}", (0 + 1).ToString());
for (var i = 0; i < itemsCout; i = i + threadCount)
{
var item = new Course
{
Name = courses[i].Name,
Id = courses[i].Id,
OwnerId = courses[i].OwnerId,
DescriptionHeading = courses[i].DescriptionHeading,
Description = courses[i].Description,
CourseState = courses[i].CourseState
};
var alias = courses[i].Id;
item = service.Courses.Create(item).Execute();
Console.WriteLine(DateTime.Now.ToString() + " - Created new course: {0} with ID {1}, and alias of {2}...", item.Name, item.Id, alias);
}
});
Thread thread2 = new Thread(() =>
{
Console.WriteLine("Started thread {0}", (1 + 1).ToString());
for (var i = 1; i < itemsCout; i = i + threadCount)
{
var item = new Course
{
Name = courses[i].Name,
Id = courses[i].Id,
OwnerId = courses[i].OwnerId,
DescriptionHeading = courses[i].DescriptionHeading,
Description = courses[i].Description,
CourseState = courses[i].CourseState
};
var alias = courses[i].Id;
item = service.Courses.Create(item).Execute();
Console.WriteLine(DateTime.Now.ToString() + " - Created new course: {0} with ID {1}, and alias of {2}...", item.Name, item.Id, alias);
}
});
Thread thread3 = new Thread(() =>
{
Console.WriteLine("Started thread {0}", (2 + 1).ToString());
for (var i = 2; i < itemsCout; i = i + threadCount)
{
var item = new Course
{
Name = courses[i].Name,
Id = courses[i].Id,
OwnerId = courses[i].OwnerId,
DescriptionHeading = courses[i].DescriptionHeading,
Description = courses[i].Description,
CourseState = courses[i].CourseState
};
var alias = courses[i].Id;
item = service.Courses.Create(item).Execute();
Console.WriteLine(DateTime.Now.ToString() + " - Created new course: {0} with ID {1}, and alias of {2}...", item.Name, item.Id, alias);
}
});
Thread thread4 = new Thread(() =>
{
Console.WriteLine("Started thread {0}", (3 + 1).ToString());
for (var i = 3; i < itemsCout; i = i + threadCount)
{
var item = new Course
{
Name = courses[i].Name,
Id = courses[i].Id,
OwnerId = courses[i].OwnerId,
DescriptionHeading = courses[i].DescriptionHeading,
Description = courses[i].Description,
CourseState = courses[i].CourseState
};
var alias = courses[i].Id;
item = service.Courses.Create(item).Execute();
Console.WriteLine(DateTime.Now.ToString() + " - Created new course: {0} with ID {1}, and alias of {2}...", item.Name, item.Id, alias);
}
});
Thread thread5 = new Thread(() =>
{
Console.WriteLine("Started thread {0}", (4 + 1).ToString());
for (var i = 4; i < itemsCout; i = i + threadCount)
{
var item = new Course
{
Name = courses[i].Name,
Id = courses[i].Id,
OwnerId = courses[i].OwnerId,
DescriptionHeading = courses[i].DescriptionHeading,
Description = courses[i].Description,
CourseState = courses[i].CourseState
};
var alias = courses[i].Id;
item = service.Courses.Create(item).Execute();
Console.WriteLine(DateTime.Now.ToString() + " - Created new course: {0} with ID {1}, and alias of {2}...", item.Name, item.Id, alias);
}
});
thread1.Start();
thread2.Start();
thread3.Start();
thread4.Start();
thread5.Start();
thread1.Join();
thread2.Join();
thread3.Join();
thread4.Join();
thread5.Join();
Console.WriteLine(DateTime.Now.ToString() + " - Done.");
Console.Read();
}
是否有任何可能的方法可以加快速度?还是仅仅是API这么慢?
谢谢!
@@ Bluescrod在创建批处理课程时,您还有问题吗?现在,我还有409个“操作已中止”。使用API进行4到7次重复调用,一一对应500个“遇到内部错误”错误。
这是我在打字稿中的代码:
dtos = [
{
uniqueName: 'p:day108.01.1951.catherine',
descriptionHeading: '',
name: 'class1'
},
{
uniqueName: 'p:day108.01.1455.july01',
descriptionHeading: '',
name: 'class2'
},
{
uniqueName: 'p:day108.01.5649.julielee',
descriptionHeading: '',
name: 'class3'
},
{
uniqueName: 'p:day108.01.2136.litda609',
descriptionHeading: '',
name: 'class4'
},
{
uniqueName: 'p:day108.01.1894.amyc7591',
descriptionHeading: '',
name: 'class5'
},
{
uniqueName: 'p:day108.01.1501.chuoii',
descriptionHeading: '',
name: 'class6'
},
];
createCourses(dtos);
createCourses(dtos: CourseCreateDTO[]): Observable<ResultSummary> {
return from(dtos).pipe(
mergeMap(dto => {
return this.classroomService.createCourse(dto).pipe(
map(result => {
if (!(result instanceof StandardError)) {
const course: GoogleClassroomCourse = result;
this.courses.push(course);
this.coursesChanged.emit();
}
return result;
}),
);
}),
toArray(),
ResultSummary.resultSummaryForArrayWithStandardError(),
defaultIfEmpty({} as ResultSummary),
);
}
createCourse(dto: CourseCreateDTO)
: Observable<GoogleClassroomCourse | StandardError> {
try {
// set up http options
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'Bearer ' + this.auth.accessToken
}),
// params: params,
body: {
id: dto.uniqueName,
name: dto.name,
descriptionHeading: dto.descriptionHeading,
ownerId: ADMIN_USERNAME + '@' + DOMAIN_NAME,
courseState: CourseStateEnum.ACTIVE,
}
};
const url = 'https://classroom.googleapis.com/v1/courses';
return this.http.request<GoogleClassroomCourse>('POST', url, httpOptions).pipe(
map((result: GoogleClassroomCourse | StandardError) => {
console.log('result', result);
if (!(result instanceof StandardError)) {
return {
...result,
courseData: this.extractCourseData(result)
} as GoogleClassroomCourse;
}
return result;
}),
);
} catch (error) {
console.log('error', error);
return of(new StandardError(error.message, dto));
}
}