|
14 | 14 | package au.org.ala.alerts
|
15 | 15 |
|
16 | 16 | import au.org.ala.userdetails.UserDetailsFromIdListRequest
|
| 17 | +import au.org.ala.userdetails.UserDetailsFromIdListResponse |
17 | 18 | import au.org.ala.web.UserDetails
|
18 | 19 | import grails.converters.JSON
|
19 | 20 | import grails.plugin.cache.Cacheable
|
@@ -71,64 +72,90 @@ class UserService {
|
71 | 72 |
|
72 | 73 | /**
|
73 | 74 | * Sync User table with UserDetails app via webservice
|
74 |
| - * TODO batch requests to userDetails in 100 lots (see @AuthService.getUserDetailsById ) |
75 | 75 | *
|
76 |
| - * @return |
| 76 | + * @return total number of updates |
77 | 77 | */
|
| 78 | +// @Transactional // transactions handled manually |
78 | 79 | int updateUserEmails() {
|
| 80 | + final int pageSize = grailsApplication.config.getProperty('alerts.user-sync.batch-size', Integer, 1000) |
79 | 81 | def toUpdate = []
|
80 |
| - log.warn "Checking all ${User.count()} users in Alerts user table." |
| 82 | + def total = User.count() |
| 83 | + log.warn "Checking all ${total} users in Alerts user table." |
81 | 84 | def count = 0
|
82 | 85 |
|
83 |
| - User.findAll().each { user -> |
84 |
| - count++ |
85 |
| - UserDetails userDetails = authService.getUserForUserId(user.userId, false) // under @Cacheable |
86 |
| - Boolean userHasChanged = false |
87 |
| - |
88 |
| - if (userDetails) { |
89 |
| - // update email |
90 |
| - if (userDetails != null && user.email != userDetails.userName) { |
91 |
| - user.email = userDetails.userName |
92 |
| - log.debug "Updating email address for user ${user.userId}: ${userDetails.userName}" |
93 |
| - userHasChanged = true |
94 |
| - } |
| 86 | + def page = 0 |
| 87 | + |
| 88 | + boolean done = false |
95 | 89 |
|
96 |
| - // update locked property |
97 |
| - if (userDetails?.hasProperty("locked") && userDetails.locked != null) { |
98 |
| - log.debug "Checking locked user: ${user.userId} -> ${userDetails.locked} vs ${user.locked}" |
| 90 | + while (!done) { |
| 91 | + User.withTransaction { |
| 92 | + List<User> users = User.findAll([sort: 'id', max: (page+1) * pageSize, offset: page * pageSize]) |
| 93 | + done = users.size() < pageSize |
| 94 | + List<User> updates = [] |
99 | 95 |
|
100 |
| - if ((user.locked == null && userDetails.locked == true) || |
101 |
| - (user.locked != null && user.locked != userDetails.locked)) { |
102 |
| - user.locked = userDetails.locked |
103 |
| - log.debug "Updating locked status for user ${user.userId}: ${userDetails.locked}" |
104 |
| - userHasChanged = true |
| 96 | + def ids = users*.userId |
| 97 | + UserDetailsFromIdListResponse results |
| 98 | + if (ids) { |
| 99 | + try { |
| 100 | + results = authService.getUserDetailsById(ids, false) |
| 101 | + } catch (Exception e) { |
| 102 | + log.warn("couldn't get user details from web service", e) |
105 | 103 | }
|
106 | 104 | }
|
107 |
| - } else { |
108 |
| - // we can't find a user in userdetails using userId - lock their account in alerts DB |
109 |
| - if ((user.locked == null || user.locked != true) && Environment.current == Environment.PRODUCTION) { |
110 |
| - user.locked = true |
111 |
| - log.warn "Updating locked status for missing user ${user.userId}: true" |
112 |
| - userHasChanged = true |
113 |
| - } |
114 |
| - } |
115 | 105 |
|
| 106 | + if (results && results.success) { |
| 107 | + users.each {user -> |
| 108 | + UserDetails userDetails = results.users[user.userId] |
| 109 | + if (userDetails) { |
| 110 | + // update email |
| 111 | + boolean update = false |
| 112 | + if (user.email != userDetails.userName) { |
| 113 | + user.email = userDetails.userName |
| 114 | + log.debug "Updating email address for user ${user.userId}: ${userDetails.userName}" |
| 115 | + update = true |
| 116 | + } |
| 117 | + |
| 118 | + // update locked property |
| 119 | + if (userDetails.locked != null) { |
| 120 | + log.debug "Checking locked user: ${user.userId} -> ${userDetails.locked} vs ${user.locked}" |
| 121 | + |
| 122 | + if ((user.locked == null && userDetails.locked == true) || |
| 123 | + (user.locked != null && user.locked != userDetails.locked)) { |
| 124 | + user.locked = userDetails.locked |
| 125 | + log.debug "Updating locked status for user ${user.userId}: ${userDetails.locked}" |
| 126 | + update = true |
| 127 | + } |
| 128 | + } |
| 129 | + if (update) { |
| 130 | + updates << user |
| 131 | + } |
| 132 | + } else { |
| 133 | + // we can't find a user in userdetails using userId - lock their account in alerts DB |
| 134 | + if ((user.locked == null || user.locked != true) && Environment.current == Environment.PRODUCTION) { |
| 135 | + user.locked = true |
| 136 | + log.warn "Updating locked status for missing user ${user.userId}: true" |
| 137 | + updates << user |
| 138 | + } |
| 139 | + } |
| 140 | + } |
| 141 | + } else if (results && !results.success) { |
| 142 | + log.warn("Unsuccessful response from userdetails: {}", results) |
| 143 | + } |
116 | 144 |
|
117 |
| - if (userHasChanged) { |
118 |
| - toUpdate << user |
| 145 | + if (updates) { |
| 146 | + updates.each { |
| 147 | + log.warn "Modifying user: ${it as JSON}" |
| 148 | + } |
| 149 | + count += updates.size() |
| 150 | + updates*.save() |
| 151 | + } |
119 | 152 | }
|
120 | 153 |
|
121 |
| - if (count % 100 == 0) { |
122 |
| - log.warn "Checked ${count} users with ${toUpdate.size()} changes, so far" |
123 |
| - } |
124 |
| - } |
| 154 | + page++ |
| 155 | + log.warn "Checked ${Math.min(total, page * pageSize)} users with ${count} changes, so far" |
125 | 156 |
|
126 |
| - toUpdate.each { |
127 |
| - log.warn "Modifying user: ${it as JSON}" |
128 |
| - it.save(flush: true) |
129 | 157 | }
|
130 |
| - |
131 |
| - toUpdate.size() |
| 158 | + return count |
132 | 159 | }
|
133 | 160 |
|
134 | 161 | User getUser(userDetailsParam = null) {
|
|
0 commit comments