Compare commits

...

3 Commits

12 changed files with 192 additions and 121 deletions

@ -209,7 +209,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/Id" $ref: "#/components/schemas/OperationID"
default: default:
description: General Error description: General Error
content: content:
@ -520,7 +520,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/Id" $ref: "#/components/schemas/OperationID"
default: default:
description: General Error description: General Error
content: content:
@ -1114,6 +1114,14 @@ components:
ID: ID:
type: integer type: integer
format: int64 format: int64
OperationID:
required:
- OperationID
type: object
properties:
OperationID:
type: integer
format: int32
Roles: Roles:
required: required:
- Roles - Roles

@ -142,7 +142,7 @@ type Invoker interface {
// Trigger the validator to create a mapfix. // Trigger the validator to create a mapfix.
// //
// POST /mapfixes // POST /mapfixes
CreateMapfix(ctx context.Context, request *MapfixTriggerCreate) (*ID, error) CreateMapfix(ctx context.Context, request *MapfixTriggerCreate) (*OperationID, error)
// CreateScript invokes createScript operation. // CreateScript invokes createScript operation.
// //
// Create a new script. // Create a new script.
@ -160,7 +160,7 @@ type Invoker interface {
// Trigger the validator to create a new submission. // Trigger the validator to create a new submission.
// //
// POST /submissions // POST /submissions
CreateSubmission(ctx context.Context, request *SubmissionTriggerCreate) (*ID, error) CreateSubmission(ctx context.Context, request *SubmissionTriggerCreate) (*OperationID, error)
// DeleteScript invokes deleteScript operation. // DeleteScript invokes deleteScript operation.
// //
// Delete the specified script by ID. // Delete the specified script by ID.
@ -2587,12 +2587,12 @@ func (c *Client) sendActionSubmissionValidated(ctx context.Context, params Actio
// Trigger the validator to create a mapfix. // Trigger the validator to create a mapfix.
// //
// POST /mapfixes // POST /mapfixes
func (c *Client) CreateMapfix(ctx context.Context, request *MapfixTriggerCreate) (*ID, error) { func (c *Client) CreateMapfix(ctx context.Context, request *MapfixTriggerCreate) (*OperationID, error) {
res, err := c.sendCreateMapfix(ctx, request) res, err := c.sendCreateMapfix(ctx, request)
return res, err return res, err
} }
func (c *Client) sendCreateMapfix(ctx context.Context, request *MapfixTriggerCreate) (res *ID, err error) { func (c *Client) sendCreateMapfix(ctx context.Context, request *MapfixTriggerCreate) (res *OperationID, err error) {
otelAttrs := []attribute.KeyValue{ otelAttrs := []attribute.KeyValue{
otelogen.OperationID("createMapfix"), otelogen.OperationID("createMapfix"),
semconv.HTTPRequestMethodKey.String("POST"), semconv.HTTPRequestMethodKey.String("POST"),
@ -2911,12 +2911,12 @@ func (c *Client) sendCreateScriptPolicy(ctx context.Context, request *ScriptPoli
// Trigger the validator to create a new submission. // Trigger the validator to create a new submission.
// //
// POST /submissions // POST /submissions
func (c *Client) CreateSubmission(ctx context.Context, request *SubmissionTriggerCreate) (*ID, error) { func (c *Client) CreateSubmission(ctx context.Context, request *SubmissionTriggerCreate) (*OperationID, error) {
res, err := c.sendCreateSubmission(ctx, request) res, err := c.sendCreateSubmission(ctx, request)
return res, err return res, err
} }
func (c *Client) sendCreateSubmission(ctx context.Context, request *SubmissionTriggerCreate) (res *ID, err error) { func (c *Client) sendCreateSubmission(ctx context.Context, request *SubmissionTriggerCreate) (res *OperationID, err error) {
otelAttrs := []attribute.KeyValue{ otelAttrs := []attribute.KeyValue{
otelogen.OperationID("createSubmission"), otelogen.OperationID("createSubmission"),
semconv.HTTPRequestMethodKey.String("POST"), semconv.HTTPRequestMethodKey.String("POST"),

@ -3676,7 +3676,7 @@ func (s *Server) handleCreateMapfixRequest(args [0]string, argsEscaped bool, w h
} }
}() }()
var response *ID var response *OperationID
if m := s.cfg.Middleware; m != nil { if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{ mreq := middleware.Request{
Context: ctx, Context: ctx,
@ -3691,7 +3691,7 @@ func (s *Server) handleCreateMapfixRequest(args [0]string, argsEscaped bool, w h
type ( type (
Request = *MapfixTriggerCreate Request = *MapfixTriggerCreate
Params = struct{} Params = struct{}
Response = *ID Response = *OperationID
) )
response, err = middleware.HookMiddleware[ response, err = middleware.HookMiddleware[
Request, Request,
@ -4261,7 +4261,7 @@ func (s *Server) handleCreateSubmissionRequest(args [0]string, argsEscaped bool,
} }
}() }()
var response *ID var response *OperationID
if m := s.cfg.Middleware; m != nil { if m := s.cfg.Middleware; m != nil {
mreq := middleware.Request{ mreq := middleware.Request{
Context: ctx, Context: ctx,
@ -4276,7 +4276,7 @@ func (s *Server) handleCreateSubmissionRequest(args [0]string, argsEscaped bool,
type ( type (
Request = *SubmissionTriggerCreate Request = *SubmissionTriggerCreate
Params = struct{} Params = struct{}
Response = *ID Response = *OperationID
) )
response, err = middleware.HookMiddleware[ response, err = middleware.HookMiddleware[
Request, Request,

@ -981,6 +981,102 @@ func (s *Operation) UnmarshalJSON(data []byte) error {
return s.Decode(d) return s.Decode(d)
} }
// Encode implements json.Marshaler.
func (s *OperationID) Encode(e *jx.Encoder) {
e.ObjStart()
s.encodeFields(e)
e.ObjEnd()
}
// encodeFields encodes fields.
func (s *OperationID) encodeFields(e *jx.Encoder) {
{
e.FieldStart("OperationID")
e.Int32(s.OperationID)
}
}
var jsonFieldsNameOfOperationID = [1]string{
0: "OperationID",
}
// Decode decodes OperationID from json.
func (s *OperationID) Decode(d *jx.Decoder) error {
if s == nil {
return errors.New("invalid: unable to decode OperationID to nil")
}
var requiredBitSet [1]uint8
if err := d.ObjBytes(func(d *jx.Decoder, k []byte) error {
switch string(k) {
case "OperationID":
requiredBitSet[0] |= 1 << 0
if err := func() error {
v, err := d.Int32()
s.OperationID = int32(v)
if err != nil {
return err
}
return nil
}(); err != nil {
return errors.Wrap(err, "decode field \"OperationID\"")
}
default:
return d.Skip()
}
return nil
}); err != nil {
return errors.Wrap(err, "decode OperationID")
}
// Validate required fields.
var failures []validate.FieldError
for i, mask := range [1]uint8{
0b00000001,
} {
if result := (requiredBitSet[i] & mask) ^ mask; result != 0 {
// Mask only required fields and check equality to mask using XOR.
//
// If XOR result is not zero, result is not equal to expected, so some fields are missed.
// Bits of fields which would be set are actually bits of missed fields.
missed := bits.OnesCount8(result)
for bitN := 0; bitN < missed; bitN++ {
bitIdx := bits.TrailingZeros8(result)
fieldIdx := i*8 + bitIdx
var name string
if fieldIdx < len(jsonFieldsNameOfOperationID) {
name = jsonFieldsNameOfOperationID[fieldIdx]
} else {
name = strconv.Itoa(fieldIdx)
}
failures = append(failures, validate.FieldError{
Name: name,
Error: validate.ErrFieldRequired,
})
// Reset bit.
result &^= 1 << bitIdx
}
}
}
if len(failures) > 0 {
return &validate.Error{Fields: failures}
}
return nil
}
// MarshalJSON implements stdjson.Marshaler.
func (s *OperationID) MarshalJSON() ([]byte, error) {
e := jx.Encoder{}
s.Encode(&e)
return e.Bytes(), nil
}
// UnmarshalJSON implements stdjson.Unmarshaler.
func (s *OperationID) UnmarshalJSON(data []byte) error {
d := jx.DecodeBytes(data)
return s.Decode(d)
}
// Encode encodes int32 as json. // Encode encodes int32 as json.
func (o OptInt32) Encode(e *jx.Encoder) { func (o OptInt32) Encode(e *jx.Encoder) {
if !o.Set { if !o.Set {

@ -933,7 +933,7 @@ func decodeActionSubmissionValidatedResponse(resp *http.Response) (res *ActionSu
return res, errors.Wrap(defRes, "error") return res, errors.Wrap(defRes, "error")
} }
func decodeCreateMapfixResponse(resp *http.Response) (res *ID, _ error) { func decodeCreateMapfixResponse(resp *http.Response) (res *OperationID, _ error) {
switch resp.StatusCode { switch resp.StatusCode {
case 201: case 201:
// Code 201. // Code 201.
@ -949,7 +949,7 @@ func decodeCreateMapfixResponse(resp *http.Response) (res *ID, _ error) {
} }
d := jx.DecodeBytes(buf) d := jx.DecodeBytes(buf)
var response ID var response OperationID
if err := func() error { if err := func() error {
if err := response.Decode(d); err != nil { if err := response.Decode(d); err != nil {
return err return err
@ -1182,7 +1182,7 @@ func decodeCreateScriptPolicyResponse(resp *http.Response) (res *ID, _ error) {
return res, errors.Wrap(defRes, "error") return res, errors.Wrap(defRes, "error")
} }
func decodeCreateSubmissionResponse(resp *http.Response) (res *ID, _ error) { func decodeCreateSubmissionResponse(resp *http.Response) (res *OperationID, _ error) {
switch resp.StatusCode { switch resp.StatusCode {
case 201: case 201:
// Code 201. // Code 201.
@ -1198,7 +1198,7 @@ func decodeCreateSubmissionResponse(resp *http.Response) (res *ID, _ error) {
} }
d := jx.DecodeBytes(buf) d := jx.DecodeBytes(buf)
var response ID var response OperationID
if err := func() error { if err := func() error {
if err := response.Decode(d); err != nil { if err := response.Decode(d); err != nil {
return err return err

@ -139,7 +139,7 @@ func encodeActionSubmissionValidatedResponse(response *ActionSubmissionValidated
return nil return nil
} }
func encodeCreateMapfixResponse(response *ID, w http.ResponseWriter, span trace.Span) error { func encodeCreateMapfixResponse(response *OperationID, w http.ResponseWriter, span trace.Span) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(201) w.WriteHeader(201)
span.SetStatus(codes.Ok, http.StatusText(201)) span.SetStatus(codes.Ok, http.StatusText(201))
@ -181,7 +181,7 @@ func encodeCreateScriptPolicyResponse(response *ID, w http.ResponseWriter, span
return nil return nil
} }
func encodeCreateSubmissionResponse(response *ID, w http.ResponseWriter, span trace.Span) error { func encodeCreateSubmissionResponse(response *OperationID, w http.ResponseWriter, span trace.Span) error {
w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(201) w.WriteHeader(201)
span.SetStatus(codes.Ok, http.StatusText(201)) span.SetStatus(codes.Ok, http.StatusText(201))

@ -455,6 +455,21 @@ func (s *Operation) SetPath(val string) {
s.Path = val s.Path = val
} }
// Ref: #/components/schemas/OperationID
type OperationID struct {
OperationID int32 `json:"OperationID"`
}
// GetOperationID returns the value of OperationID.
func (s *OperationID) GetOperationID() int32 {
return s.OperationID
}
// SetOperationID sets the value of OperationID.
func (s *OperationID) SetOperationID(val int32) {
s.OperationID = val
}
// NewOptInt32 returns new OptInt32 with value set to v. // NewOptInt32 returns new OptInt32 with value set to v.
func NewOptInt32(v int32) OptInt32 { func NewOptInt32(v int32) OptInt32 {
return OptInt32{ return OptInt32{

@ -121,7 +121,7 @@ type Handler interface {
// Trigger the validator to create a mapfix. // Trigger the validator to create a mapfix.
// //
// POST /mapfixes // POST /mapfixes
CreateMapfix(ctx context.Context, req *MapfixTriggerCreate) (*ID, error) CreateMapfix(ctx context.Context, req *MapfixTriggerCreate) (*OperationID, error)
// CreateScript implements createScript operation. // CreateScript implements createScript operation.
// //
// Create a new script. // Create a new script.
@ -139,7 +139,7 @@ type Handler interface {
// Trigger the validator to create a new submission. // Trigger the validator to create a new submission.
// //
// POST /submissions // POST /submissions
CreateSubmission(ctx context.Context, req *SubmissionTriggerCreate) (*ID, error) CreateSubmission(ctx context.Context, req *SubmissionTriggerCreate) (*OperationID, error)
// DeleteScript implements deleteScript operation. // DeleteScript implements deleteScript operation.
// //
// Delete the specified script by ID. // Delete the specified script by ID.

@ -180,7 +180,7 @@ func (UnimplementedHandler) ActionSubmissionValidated(ctx context.Context, param
// Trigger the validator to create a mapfix. // Trigger the validator to create a mapfix.
// //
// POST /mapfixes // POST /mapfixes
func (UnimplementedHandler) CreateMapfix(ctx context.Context, req *MapfixTriggerCreate) (r *ID, _ error) { func (UnimplementedHandler) CreateMapfix(ctx context.Context, req *MapfixTriggerCreate) (r *OperationID, _ error) {
return r, ht.ErrNotImplemented return r, ht.ErrNotImplemented
} }
@ -207,7 +207,7 @@ func (UnimplementedHandler) CreateScriptPolicy(ctx context.Context, req *ScriptP
// Trigger the validator to create a new submission. // Trigger the validator to create a new submission.
// //
// POST /submissions // POST /submissions
func (UnimplementedHandler) CreateSubmission(ctx context.Context, req *SubmissionTriggerCreate) (r *ID, _ error) { func (UnimplementedHandler) CreateSubmission(ctx context.Context, req *SubmissionTriggerCreate) (r *OperationID, _ error) {
return r, ht.ErrNotImplemented return r, ht.ErrNotImplemented
} }

@ -5,6 +5,18 @@ package model
// Requests are sent from maps-service to validator // Requests are sent from maps-service to validator
type CreateSubmissionRequest struct {
// operation_id is passed back in the response message
OperationID int32
ModelID int64
}
type CreateMapfixRequest struct {
OperationID int32
ModelID int64
TargetAssetID int64
}
type ValidateSubmissionRequest struct { type ValidateSubmissionRequest struct {
// submission_id is passed back in the response message // submission_id is passed back in the response message
SubmissionID int64 SubmissionID int64

@ -46,7 +46,7 @@ var (
) )
// POST /mapfixes // POST /mapfixes
func (svc *Service) CreateMapfix(ctx context.Context, request *api.MapfixCreate) (*api.ID, error) { func (svc *Service) CreateMapfix(ctx context.Context, request *api.MapfixTriggerCreate) (*api.OperationID, error) {
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
if !ok { if !ok {
return nil, ErrUserInfo return nil, ErrUserInfo
@ -57,59 +57,29 @@ func (svc *Service) CreateMapfix(ctx context.Context, request *api.MapfixCreate)
return nil, err return nil, err
} }
// Check if user's mapfixes in the creation phase exceeds the limit operation, err := svc.DB.Operations().Create(ctx, model.Operation{
{ Owner: int64(userId),
filter := datastore.Optional() StatusID: model.OperationStatusCreated,
filter.Add("submitter", int64(userId))
filter.Add("status_id", CreationPhaseMapfixStatuses)
creation_mapfixes, err := svc.DB.Mapfixes().List(ctx, filter, model.Page{
Number: 1,
Size: int32(CreationPhaseMapfixesLimit),
},datastore.ListSortDisabled)
if err != nil {
return nil, err
}
if CreationPhaseMapfixesLimit <= len(creation_mapfixes) {
return nil, ErrCreationPhaseMapfixesLimit
}
}
// Check if an active mapfix with the same asset id exists
{
filter := datastore.Optional()
filter.Add("asset_id", request.AssetID)
filter.Add("asset_version", request.AssetVersion)
filter.Add("status_id", ActiveMapfixStatuses)
active_mapfixes, err := svc.DB.Mapfixes().List(ctx, filter, model.Page{
Number: 1,
Size: 1,
},datastore.ListSortDisabled)
if err != nil {
return nil, err
}
if len(active_mapfixes) != 0{
return nil, ErrActiveMapfixSameAssetID
}
}
mapfix, err := svc.DB.Mapfixes().Create(ctx, model.Mapfix{
ID: 0,
DisplayName: request.DisplayName,
Creator: request.Creator,
GameID: request.GameID,
Submitter: int64(userId),
AssetID: request.AssetID,
AssetVersion: request.AssetVersion,
Completed: false,
TargetAssetID: request.TargetAssetID,
StatusID: model.MapfixStatusUnderConstruction,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &api.ID{
ID: mapfix.ID, create_request := model.CreateMapfixRequest{
OperationID: operation.ID,
ModelID: request.AssetID,
TargetAssetID: request.TargetAssetID,
}
j, err := json.Marshal(create_request)
if err != nil {
return nil, err
}
svc.Nats.Publish("maptest.mapfixes.create", []byte(j))
return &api.OperationID{
OperationID: operation.ID,
}, nil }, nil
} }

@ -49,7 +49,7 @@ var (
) )
// POST /submissions // POST /submissions
func (svc *Service) CreateSubmission(ctx context.Context, request *api.SubmissionCreate) (*api.ID, error) { func (svc *Service) CreateSubmission(ctx context.Context, request *api.SubmissionTriggerCreate) (*api.OperationID, error) {
userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle) userInfo, ok := ctx.Value("UserInfo").(UserInfoHandle)
if !ok { if !ok {
return nil, ErrUserInfo return nil, ErrUserInfo
@ -60,58 +60,28 @@ func (svc *Service) CreateSubmission(ctx context.Context, request *api.Submissio
return nil, err return nil, err
} }
// Check if user's submissions in the creation phase exceeds the limit operation, err := svc.DB.Operations().Create(ctx, model.Operation{
{ Owner: int64(userId),
filter := datastore.Optional() StatusID: model.OperationStatusCreated,
filter.Add("submitter", int64(userId))
filter.Add("status_id", CreationPhaseSubmissionStatuses)
creation_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{
Number: 1,
Size: int32(CreationPhaseSubmissionsLimit),
},datastore.ListSortDisabled)
if err != nil {
return nil, err
}
if CreationPhaseSubmissionsLimit <= len(creation_submissions) {
return nil, ErrCreationPhaseSubmissionsLimit
}
}
// Check if an active submission with the same asset id exists
{
filter := datastore.Optional()
filter.Add("asset_id", request.AssetID)
filter.Add("asset_version", request.AssetVersion)
filter.Add("status_id", ActiveSubmissionStatuses)
active_submissions, err := svc.DB.Submissions().List(ctx, filter, model.Page{
Number: 1,
Size: 1,
},datastore.ListSortDisabled)
if err != nil {
return nil, err
}
if len(active_submissions) != 0{
return nil, ErrActiveSubmissionSameAssetID
}
}
submission, err := svc.DB.Submissions().Create(ctx, model.Submission{
ID: 0,
DisplayName: request.DisplayName,
Creator: request.Creator,
GameID: request.GameID,
Submitter: int64(userId),
AssetID: request.AssetID,
AssetVersion: request.AssetVersion,
Completed: false,
StatusID: model.SubmissionStatusUnderConstruction,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &api.ID{
ID: submission.ID, create_request := model.CreateSubmissionRequest{
OperationID: operation.ID,
ModelID: request.AssetID,
}
j, err := json.Marshal(create_request)
if err != nil {
return nil, err
}
svc.Nats.Publish("maptest.submissions.create", []byte(j))
return &api.OperationID{
OperationID: operation.ID,
}, nil }, nil
} }