11package com.team1.hangsha.event.controller
22
3+ import com.fasterxml.jackson.core.JsonToken
4+ import com.fasterxml.jackson.databind.ObjectMapper
35import com.team1.hangsha.event.dto.core.CrawledProgramEvent
46import com.team1.hangsha.event.dto.request.EventPatchRequest
57import com.team1.hangsha.event.repository.EventRepository
68import com.team1.hangsha.event.service.EventSyncService
9+ import org.springframework.http.HttpStatus
710import org.springframework.web.bind.annotation.DeleteMapping
8- import org.springframework.web.bind.annotation.PostMapping
911import org.springframework.web.bind.annotation.PatchMapping
1012import org.springframework.web.bind.annotation.PathVariable
13+ import org.springframework.web.bind.annotation.PostMapping
1114import org.springframework.web.bind.annotation.RequestBody
15+ import org.springframework.web.bind.annotation.RequestParam
1216import org.springframework.web.bind.annotation.RequestMapping
1317import org.springframework.web.bind.annotation.RestController
18+ import org.springframework.web.server.ResponseStatusException
19+ import org.springframework.web.multipart.MultipartFile
1420
1521@RestController
1622@RequestMapping(" /admin/events" )
1723class EventSyncController (
1824 private val eventSyncService : EventSyncService ,
1925 private val eventRepository : EventRepository ,
26+ private val objectMapper : ObjectMapper ,
2027) {
2128 @PostMapping(" /sync" )
2229 fun sync (
2330 @RequestBody events : List <CrawledProgramEvent >,
2431 ): Map <String , Any > {
32+ return runSync(events)
33+ }
34+
35+ @PostMapping(" /sync" , consumes = [" multipart/form-data" ])
36+ fun syncByFile (
37+ @RequestParam(" file" ) file : MultipartFile ,
38+ ): Map <String , Any > {
39+ file.inputStream.use { input ->
40+ objectMapper.factory.createParser(input).use { parser ->
41+ if (parser.nextToken() != JsonToken .START_ARRAY ) {
42+ throw ResponseStatusException (HttpStatus .BAD_REQUEST , " file must be a JSON array" )
43+ }
44+
45+ var total = 0
46+ var upserted = 0
47+ var skipped = 0
48+ val buffer = ArrayList <CrawledProgramEvent >(SYNC_BATCH_SIZE )
49+
50+ while (parser.nextToken() != JsonToken .END_ARRAY ) {
51+ val event = objectMapper.readValue(parser, CrawledProgramEvent ::class .java)
52+ buffer.add(event)
53+
54+ if (buffer.size >= SYNC_BATCH_SIZE ) {
55+ val result = eventSyncService.sync(buffer)
56+ total + = result.total
57+ upserted + = result.upserted
58+ skipped + = result.skipped
59+ buffer.clear()
60+ }
61+ }
62+
63+ if (buffer.isNotEmpty()) {
64+ val result = eventSyncService.sync(buffer)
65+ total + = result.total
66+ upserted + = result.upserted
67+ skipped + = result.skipped
68+ }
69+
70+ return mapOf (
71+ " ok" to true ,
72+ " total" to total,
73+ " upserted" to upserted,
74+ " skipped" to skipped,
75+ )
76+ }
77+ }
78+ }
79+
80+ private fun runSync (events : List <CrawledProgramEvent >): Map <String , Any > {
2581 val result = eventSyncService.sync(events)
2682 return mapOf (
2783 " ok" to true ,
@@ -47,4 +103,8 @@ class EventSyncController(
47103 fun deleteEvent (
48104 @PathVariable eventId : Long ,
49105 ): Map <String , Any > = eventSyncService.deleteEvent(eventId)
106+
107+ companion object {
108+ private const val SYNC_BATCH_SIZE = 500
109+ }
50110}
0 commit comments